{"id":105620,"date":"2025-03-20T22:05:00","date_gmt":"2025-03-20T22:05:00","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=105620"},"modified":"2025-02-13T22:17:24","modified_gmt":"2025-02-13T22:17:24","slug":"mysql-vs-postgresql-string-datatypes","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/mysql\/mysql-vs-postgresql-string-datatypes\/","title":{"rendered":"MySQL vs PostgreSQL \u2013 String Datatypes"},"content":{"rendered":"\n<p>A very common task in creating a database is to store string data. For example, words, paragraph(s) or even documents. String data types allow you to do just that and store and represent text. They handle everything from simple names and addresses to complex data.<\/p>\n\n\n\n<p>A string is simply a sequence of characters. These characters can be letters, numbers, symbols, or even spaces. For example, &#8220;Simple Talk&#8221;, &#8220;MySQL and PostgreSQL&#8221;, &#8220;1234&#8221; are all strings. Think of each character as a building block. A string is made up of these blocks, arranged in a specific order.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-1.jpeg\" alt=\"\" class=\"wp-image-105621\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-1.jpeg 1920w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-1-300x169.jpeg 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-1-1024x576.jpeg 1024w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-1-768x432.jpeg 768w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-1-1536x864.jpeg 1536w\" sizes=\"auto, (max-width: 1920px) 100vw, 1920px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>String data types are important in database management systems. Let&#8217;s say you are trying to store some user information in a table. You want to be able to handle values of varying lengths, for example email addresses that can accommodate different email lengths. Some values will have a fixed length, like identification numbers. There are also varying characters you may need so store and deal with from different languages and today, even emojis.<\/p>\n\n\n\n<p>In addition to standard string types, MySQL and PostgreSQL offer special string data types that help structure data in specific ways. For example, the <code>ENUM<\/code> type in both databases lets you define a list of allowed values for a column. We\u2019ll explore how each database handles <code>ENUM<\/code> and what makes them different.<\/p>\n\n\n\n<p>MySQL also has a <code>SET<\/code> type, which lets you store multiple values from a predefined list in a single field. PostgreSQL doesn\u2019t have a direct equivalent, but it has the <code>ARRAY<\/code> type, which lets you store a list of values in one column. Arrays in PostgreSQL are very flexible\u2014you can search, pick specific parts, and do other operations on them. We\u2019ll also take a closer look at how this works.<\/p>\n\n\n\n<p>MySQL and PostgreSQL offer a variety of string data types we can implement into our databases. Let\u2019s dive in and explore how these string data types work in both of these powerful database systems.<\/p>\n\n\n\n<p><em>Note: One thing I am not covering in this article, that is very important, is character sets and collations. That was covered in <\/em><a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/mysql\/mysql-vs-postgresql-character-sets-and-collations\/https:\/www.red-gate.com\/simple-talk\/databases\/mysql\/mysql-vs-postgresql-character-sets-and-collations\/\"><em>the previous article here<\/em><\/a><em>.<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-mysql-string-data-types\"><a id=\"post-105620-_heading=h.3dy6vkm\"><\/a>MySQL String Data Types<\/h2>\n\n\n\n<p>MySQL DBMS provides a range of string data types for fixed-length and variable-length strings, ranging from a single character to very large text storage. Knowing when to choose the right string data type is important because it affects how your text is stored and how fast your database can retrieve and process it.<\/p>\n\n\n\n<p>In this section, we will go into details of the string data types available in MySQL while also highlighting their characteristics and functionalities. Here is a complete breakdown:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\n<p><strong>Data Type Name<\/strong><\/p>\n<\/td><td>\n<p><strong>Description<\/strong><\/p>\n<\/td><td>\n<p><strong>Common Use cases<\/strong><\/p>\n<\/td><\/tr><tr><td>\n<p><strong>CHAR(n)<\/strong><\/p>\n<\/td><td>\n<p>It is a fixed-length character string that is filled with spaces to the defined length n.<\/p>\n<\/td><td>\n<p>For storing codes with a fixed number of characters.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>VARCHAR(n)<\/strong><\/p>\n<\/td><td>\n<p>It is a variable-length character string that stores only the actual length of the text, up to a maximum length n.<\/p>\n<\/td><td>\n<p>It is more efficient for most use cases when you know the maximum length of the text (e.g., names, emails, or usernames).<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>TINYTEXT<\/strong><\/p>\n<\/td><td>\n<p>A small text string capable of storing up to 255 characters.<\/p>\n<\/td><td>\n<p>Comments or small notes. Typically items you don\u2019t want to sort on.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>TEXT<\/strong><\/p>\n<\/td><td>\n<p>It is a standard text string, capable of storing up to 65,535 bytes (about 64 KB).<\/p>\n<\/td><td>\n<p>Use <code>TEXT<\/code> for very large, unpredictable text (e.g., blog posts, comments), but be aware it may have slower performance for queries and sorting.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>MEDIUMTEXT<\/strong><\/p>\n<\/td><td>\n<p>It is a medium-length text string, capable of storing up to 16,777,215 bytes (about 16 MB).<\/p>\n<\/td><td>\n<p>Use <code>MEDIUMTEXT<\/code> when <code>TEXT<\/code> isn\u2019t enough but <code>LONGTEXT<\/code> is excessive such as longer blog posts or articles.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>LONGTEXT<\/strong><\/p>\n<\/td><td>\n<p>It is a large text string, capable of storing up to 4,294,967,295 bytes (about 4 GB).<\/p>\n<\/td><td>\n<p>Use for very large text, like entire documents or logs, with a maximum size of 4 GB<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>BINARY(n)<\/strong><\/p>\n<\/td><td>\n<p>It is a fixed-length binary data, like CHAR but for non-text data.<\/p>\n<\/td><td>\n<p>Storing encrypted keys.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>VARBINARY(N)<\/strong><\/p>\n<\/td><td>\n<p>It is a variable-length binary data, like VARCHAR but for non-text data.<\/p>\n<\/td><td>\n<p>Storing files, Images.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>TINYBLOB<\/strong><\/p>\n<\/td><td>\n<p>It is a binary large object that stores data up to 255 bytes.<\/p>\n<\/td><td>\n<p>For storing small binary files, like icons<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>BLOB<\/strong><\/p>\n<\/td><td>\n<p>It is a binary large object that stores data, up to 65,535 bytes.<\/p>\n<\/td><td>\n<p>For storing audio files, images.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>MEDIUMBLOB<\/strong><\/p>\n<\/td><td>\n<p>It is a binary large object that stores data, up to 16777215 bytes (16 MB)<\/p>\n<\/td><td>\n<p>Storing multimedia files, like videos.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>LONGBLOB<\/strong><\/p>\n<\/td><td>\n<p>It is a very large binary object that stores data, up to 4 billion bytes.<\/p>\n<\/td><td>\n<p>Storing high quality movies, documentaries.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>ENUM<\/strong><\/p>\n<\/td><td>\n<p>A text that can only be one value from a list you define.<\/p>\n<\/td><td>\n<p>Storing categorical data, such as gender, status.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>SET<\/strong><\/p>\n<\/td><td>\n<p>A text that can hold one or more values from a list you define.<\/p>\n<\/td><td>\n<p>Storing multiple options, like colours.<\/p>\n<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><code>VARCHAR(n)<\/code>, <code>CHAR(n)<\/code>, and the <code>TEXT<\/code> datatypes are ways to store text in a database, but they work differently and are useful for different situations. Here&#8217;s an easy way to understand their differences:<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-data-type-discussion\"><a id=\"post-105620-_heading=h.an6d82yolcqq\"><\/a>Data type discussion<\/h2>\n\n\n\n<p>In this section I am going to cover a bit of why you might choose one type or another for different uses. Some of the datatypes are so similar, but there are internal differences that dictate why you might choose one over the other.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-when-is-varchar-n-better\">When is VARCHAR(n) Better?<\/h3>\n\n\n\n<p>The <code>VARCHAR(n)<\/code> data type in MySQL is used to store variable-length text up to 65,535 bytes. (If you need more, you can use the <code>MEDIUMTEXT<\/code> or <code>LONGTEXT<\/code> datatypes, which I will note later in this section).<\/p>\n\n\n\n<p>The <code>VARCHAR(n)<\/code> data type can hold very large pieces of text, up to 65,535 characters (about 64 KB). In can be indexed, but the max key length for an index is 1017 bytes.<\/p>\n\n\n\n<p>The <code>VARCHAR<\/code> data type also only uses as much space as the actual text needs (based on the length of the data). So, it doesn\u2019t waste storage space to make this a variable length column.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-when-is-char-n-better\"><a id=\"post-105620-_heading=h.jzwvbkubbvz9\"><\/a>When is CHAR(n) Better?<\/h3>\n\n\n\n<p><code>CHAR(n)<\/code> is good for fixed-length text values. It has a maximum length of 255 characters and is ideal when you know exactly how long the text will always be, like country codes (&#8220;USA&#8221;, &#8220;CAN&#8221;) or short answers (&#8220;YES&#8221;, &#8220;NO&#8221;). It is best used when the data is exactly the length of the datatype, or very close to the length.<\/p>\n\n\n\n<p>It&#8217;s not particularly great for things like long descriptions or notes because you need to know the exact size of the text in advance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-what-about-text-data-types\"><a id=\"post-105620-_heading=h.a2ufnxrtfsx\"><\/a>What about TEXT data types?<\/h3>\n\n\n\n<p>While the base <code>CHAR<\/code> and <code>VARCHAR<\/code> datatypes are the datatypes you most typically will use for storing textual data, there are also a set of data types that are hold string data that are similar, but different than those data types:<\/p>\n\n\n\n<p>In MySQL, the <code>TEXT<\/code> data types are used to store large amounts of text data. There are four main types as were described in the table earlier: <code>TINYTEXT<\/code>, <code>TEXT<\/code>, <code>MEDIUMTEXT<\/code>, and <code>LONGTEXT<\/code>. Each has a max amount of text it can hold.<\/p>\n\n\n\n<p>What is interesting about these is that <code>TINYTEXT<\/code> has the same max number of characters as a <code>CHAR<\/code> type, and <code>TEXT<\/code> and <code>VARCHAR<\/code> have the same upper bounds and use only as much space as the actual text requires (plus a 1 or 2 byte overhead to capture the size of the value being stored for variable types. <code>CHAR<\/code> does not incur this cost.)<\/p>\n\n\n\n<p>The biggest difference between these different types of <code>TEXT<\/code> is that they are not manipulated in the database server\u2019s memory in the same way that a <code>VARCHAR<\/code> value is. So, searching for values stored in a <code>TINYTEXT<\/code> column can be costly compared to a <code>VARCHAR(255)<\/code>.<\/p>\n\n\n\n<p>Indexes on <code>TEXT<\/code> columns are possible, but you are required to always use a fixed amount of space, and they require a prefix index to do so. So if you have a column that is declared name <code>TINYTEXT<\/code> for example, to add an index, you would need to specify how much of the 255 bytes you want to have indexed, such as name(200). Beware that indexes on any of the <code>TEXT<\/code> types behave like a fixed length value, using all of the bytes for every index key value. So every index key value for the name(200) index would use 200 bytes.<\/p>\n\n\n\n<p>That&#8217;s why the suggestion is to use `<code>TEXT<\/code>` for values that are rarely searched or sorted, such as addresses or comments. Here&#8217;s how you can store and retrieve text strings using the <code>TEXT<\/code> data type in both MySQL and PostgreSQL:<\/p>\n\n\n\n<p>MySQL:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE messages (\n    id INT AUTO_INCREMENT PRIMARY KEY,\n    content TEXT\n);\n\nINSERT INTO messages (content) \nVALUES ('Hello, this is a sample message.');<\/pre>\n\n\n\n<p>PostgreSQL:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE messages (\n    id SERIAL PRIMARY KEY,\n    content TEXT\n);\n\nINSERT INTO messages (content) \nVALUES ('Hello, this is a sample message.');<\/pre>\n\n\n\n<p>You can retrieve data the same way in both databases using the same query:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT content \nFROM messages WHERE id = 1;<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"253\" height=\"87\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-2.png\" alt=\"\" class=\"wp-image-105622\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-the-blob-types\"><a id=\"post-105620-_heading=h.5tfqxniwfim2\"><\/a><a id=\"post-105620-_heading=h.1t3h5sf\"><\/a><a id=\"post-105620-_heading=h.4d34og8\"><\/a>THE BLOB TYPES<\/h3>\n\n\n\n<p>The BLOB type is designed for storing binary data, such as files, images, audio, videos, or any non-text content in binary format, meaning it is treated as raw bytes, with no character encoding. The BLOB type in MySQL comes in four variants, which is, <code>TINYBLOB<\/code>, <code>BLOB<\/code>, <code>MEDIUMBLOB<\/code>, and <code>LONGBLOB<\/code>.<\/p>\n\n\n\n<p><em>Note: While BLOB types are not strictly string types, you can use them to hold string values in their binary form.<\/em><\/p>\n\n\n\n<p>Let\u2019s look at a quick demo to show how you can use <code>BLOB<\/code> to store small binary files, like images in MySQL. Firstly, we start out by creating a table:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE icons (\n    id INT PRIMARY KEY,\n    name VARCHAR(50),\n    data BLOB\n);<\/pre>\n\n\n\n<p>The next step is to run the following command in MySQL to check the <code>secure_file_priv<\/code> setting. This helps us verify the path where our image file should be stored.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SHOW VARIABLES LIKE 'secure_file_priv';<\/pre>\n\n\n\n<p>The following command should return a directory path similar to the image below, you will need to copy and paste the image into this directory.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"499\" height=\"90\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-3.png\" alt=\"\" class=\"wp-image-105623\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-3.png 499w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-3-300x54.png 300w\" sizes=\"auto, (max-width: 499px) 100vw, 499px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, use the <code>LOAD_FILE<\/code> function to insert the image data into the BLOB column:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO icons (id, name, data) \nVALUES (2, 'example_icon', \n   LOAD_FILE('C:\/ProgramData\/MySQL\/MySQL Server 9.0\/Uploads\/icon.png'));<\/pre>\n\n\n\n<p>Use a <code>SELECT<\/code> statement to view the table<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT name, data FROM icons WHERE id = 2;<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"240\" height=\"86\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-4.png\" alt=\"\" class=\"wp-image-105624\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This is what your output should look like in your MySQL database. If we want to be more practical and try to display the blob data (image), we will need to use a Programming language like Python or JavaScript.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-enumerated-data-type-enum-in-mysql\">Enumerated Data Type (ENUM) in MySQL<\/h3>\n\n\n\n<p>In MySQL, the <code>ENUM<\/code> data type allows you to define a column that can only hold one value from a predefined list of options. This is useful for storing things like status values, categories, or other fixed sets of data.<\/p>\n\n\n\n<p>Example:<\/p>\n\n\n\n<p>Let&#8217;s create a table that uses an <code>ENUM<\/code> for the status column in a tasks table.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE tasks (\n    id INT AUTO_INCREMENT PRIMARY KEY,\n    name VARCHAR(255),\n    status ENUM('pending', 'in_progress', 'completed') NOT NULL\n);<\/pre>\n\n\n\n<p>In this example, the status column can only have one of the three values: &#8216;pending&#8217;, &#8216;in_progress&#8217;, or &#8216;completed&#8217;. You can insert values into the table using one of the predefined values:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO tasks (name, status) \nVALUES ('Complete documentation', 'in_progress'),\n       ('Complete API documentation', 'in_progress'), \n       ('Test APIs', 'completed');\n\nSELECT * FROM tasks;<\/pre>\n\n\n\n<p>This is what the output looks like.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"391\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-5.png\" alt=\"\" class=\"wp-image-105625\" style=\"width:413px;height:auto\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-5.png 835w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-5-300x140.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-5-768x360.png 768w\" sizes=\"auto, (max-width: 835px) 100vw, 835px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>If you try to insert a value that isn&#8217;t in the <code>ENUM<\/code> list:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO tasks (name, status) \nVALUES ('Submit report', 'done');<\/pre>\n\n\n\n<p>MySQL will return an error:<\/p>\n\n\n\n<p><code>Error Code: 1265 Data truncated for column \u2018status\u2019 at row 1<\/code><\/p>\n\n\n\n<p>This is because &#8216;done&#8217; is not in the <code>ENUM<\/code> list, hence, the data cannot be added to the column.<\/p>\n\n\n\n<p>We can also just retrieve a specific data from our table using our SELECT statement. For example:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT * \nFROM tasks \nWHERE status = 'completed';<\/pre>\n\n\n\n<p>This is what the output looks like.<\/p>\n\n\n\n<figure class=\"wp-block-image is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"215\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-6.png\" alt=\"\" class=\"wp-image-105626\" style=\"width:409px;height:auto\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-6.png 835w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-6-300x77.png 300w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-6-768x198.png 768w\" sizes=\"auto, (max-width: 835px) 100vw, 835px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-set-data-type-in-mysql\">SET Data Type in MySQL<\/h3>\n\n\n\n<p>The <code>SET<\/code> data type in MySQL is used to store multiple string values from a predefined list of options. Unlike <code>ENUM<\/code>, which only allows a single value, <code>SET<\/code> allows you to select zero, one, or more values from the list.<\/p>\n\n\n\n<p>It is similar to an array, but only allows string values in MySQL. This comes in handy when you need to represent multiple choices in a single column.<\/p>\n\n\n\n<p><strong>Example:<\/strong><\/p>\n\n\n\n<p>First, I will create a table with a <code>SET<\/code> column:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE user_preferences (\n    user_id INT PRIMARY KEY,\n    preferences SET('email_notifications', \n                    'sms_notifications', 'push_notifications')\n);<\/pre>\n\n\n\n<p>The preferences column can store any combination of the three defined options. As an example, I will insert values into the <code>SET<\/code> column that match the data <code>SET<\/code> values:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO user_preferences (user_id, preferences) \nVALUES \n(1, 'email_notifications,sms_notifications'), -- Multiple values\n(2, 'push_notifications'),                    -- Single value\n(3, '');                                      -- No value<\/pre>\n\n\n\n<p>Retrieve your data using a SELECT statement<\/p>\n\n\n\n<p>SELECT * FROM user_preferences;<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"348\" height=\"88\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-7.png\" alt=\"\" class=\"wp-image-105627\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-7.png 348w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-7-300x76.png 300w\" sizes=\"auto, (max-width: 348px) 100vw, 348px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>The first statement inserts multiple values into the row thanks to the <code>SET<\/code> data type. It also allows you to insert a single value into the <code>SET<\/code> column and also no value. Yes, no value. When no value is inserted into the <code>SET<\/code> column, it returns an empty string. An empty string is not the same as <code>NULL<\/code>.<\/p>\n\n\n\n<p>An empty string is a valid string value, it is a string with no characters. <code>NULL<\/code> indicates the absence of a value or an unknown value. If you want to explicitly store <code>NULL<\/code> for a column, you would use the keyword <code>NULL<\/code> in the <code>VALUES<\/code> list. This stores a <code>NULL<\/code> value indicating the absence of a value or an unknown value.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO user_preferences (user_id, preferences)\nVALUES (4, NULL); <\/pre>\n\n\n\n<p>Then in the table you would see a <code>NULL<\/code> for the row with <code>user_id = 4<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"349\" height=\"114\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-8.png\" alt=\"\" class=\"wp-image-105628\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-8.png 349w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-8-300x98.png 300w\" sizes=\"auto, (max-width: 349px) 100vw, 349px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Even though <code>SET<\/code> is efficient for storing multiple options, its use is limited to predefined lists, and modifications to the list (like adding or removing values) require altering the table. Now, let\u2019s check out string data types in Postgres!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-postgresql-string-data-type\"><a id=\"post-105620-_heading=h.2s8eyo1\"><\/a>PostgreSQL String Data Type<\/h2>\n\n\n\n<p>In the following table is a list of the various types of string datatypes that are available in PostgreSQL.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\n<p><strong> Data Type Name<\/strong><\/p>\n<\/td><td>\n<p><strong>Description<\/strong><\/p>\n<\/td><td>\n<p><strong>Common Use cases<\/strong><\/p>\n<\/td><\/tr><tr><td>\n<p><strong>CHARACTER(n)<\/strong><\/p>\n<p><strong>Or CHAR(n)<\/strong><\/p>\n<\/td><td>\n<p>A fixed-length character string. If the input is shorter than n, it is padded with spaces.<\/p>\n<\/td><td>\n<p>For storing country codes, area codes, etc.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>CHARACTER VARYING(n) <\/strong><\/p>\n<p><strong>Or VARCHAR(n)<\/strong><\/p>\n<\/td><td>\n<p>A variable-length character string, with a maximum length of n. Only stores actual input length.<\/p>\n<\/td><td>\n<p>For storing text fields with variable content length (e.g., names, emails, addresses), but with a defined maximum size.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>BPCHAR(n)<\/strong><\/p>\n<\/td><td>\n<p>Internal name for <code>CHAR(n)<\/code> or <code>CHARACTER(n)<\/code>. Stands for &#8220;blank-padded CHAR&#8221;.<\/p>\n<\/td><td>\n<p>Same as <code>CHARACTER(n)<\/code> or <code>CHAR(n)<\/code> &#8211; fixed-length strings where space padding is allowed.<\/p>\n<\/td><\/tr><tr><td>\n<p><strong>TEXT<\/strong><\/p>\n<\/td><td>\n<p>A <strong>variable-length<\/strong> string with no defined maximum length. It can store any length of text.<\/p>\n<\/td><td>\n<p>Articles, descriptions, etc<\/p>\n<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>In PostgreSQL, the binary data type `BYTEA` isn&#8217;t technically a string data type, but it is often compared to MySQL&#8217;s binary types. Binary data is held in a <code>`BYTEA`<\/code> data type in PostgreSQL and see how it stacks up against the binary string data types in MySQL.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\n<p><strong> Data Type <\/strong><\/p>\n<\/td><td>\n<p><strong>Name<\/strong><\/p>\n<\/td><td>\n<p><strong> Description<\/strong><\/p>\n<\/td><td>\n<p><strong> Common Use cases<\/strong><\/p>\n<\/td><\/tr><tr><td>\n<p>Binary Type<\/p>\n<\/td><td>\n<p><code>BYTEA<\/code><\/p>\n<\/td><td>\n<p>Binary data type for storing binary strings in variable length with a maximum of 1GB.<\/p>\n<\/td><td>\n<p>Storing binary files like images, documents, or any raw binary data.<\/p>\n<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>In PostgreSQL, the <code>`BYTEA`<\/code> data type is used for storing binary data (like images, files, or other non-text data). It&#8217;s similar to storing raw bytes in a column.<\/p>\n\n\n\n<p>When inserting or selecting `BYTEA` data, it is typically helpful to encodes it in a specific format (like hexadecimal or escape format when inserting data as a string value in code) to ensure its stored correctly. It&#8217;s particularly useful for handling large binary files like images, videos, or encrypted data in a structured database system.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-enum-enumerated-data-type-in-postgresql\"><a id=\"post-105620-_heading=h.17dp8vu\"><\/a>ENUM (Enumerated Data Type) in PostgreSQL<\/h3>\n\n\n\n<p>The <code>ENUM<\/code> data type allows you to define a list of predefined values. Each value represents a specific state or category, and only one of those values can be stored in a column at a time. This is useful when you want to limit the values a column can accept to a fixed set.<\/p>\n\n\n\n<p><strong>Example Use Case:<\/strong><\/p>\n\n\n\n<p>You have a table for orders, and the status of each order can only be one of a few values like &#8216;pending&#8217;, &#8216;shipped&#8217;, or &#8216;delivered&#8217;. Using <code>ENUM<\/code>, you can define these possible statuses by:<\/p>\n\n\n\n<p>First, we define the <code>order_stat<\/code>us type with the allowed values: &#8216;pending&#8217;, &#8216;shipped&#8217;, and &#8216;delivered&#8217;.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TYPE order_status AS ENUM ('pending', 'shipped', 'delivered');<\/pre>\n\n\n\n<p>Now, let&#8217;s create a table called orders, where the status column uses the order_status type.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE orders (\n    order_id SERIAL PRIMARY KEY,\n    customer_name TEXT,\n    status order_status DEFAULT 'pending' -- Default status is 'pending'\n);<\/pre>\n\n\n\n<p>We can now insert data into the orders table, specifying the status from our <code>ENUM<\/code> type.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO orders (customer_name, status)  \nVALUES   ('John Doe', 'shipped'), \n         ('Jane Smith', 'delivered'), \n         ('Emily Johnson', 'pending'),  \n         ('Aisha Bukar', DEFAULT);  <\/pre>\n\n\n\n<p>To check the inserted data, you can simply run a <code>SELECT<\/code> query.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT * FROM orders;<\/pre>\n\n\n\n<p>This would output something like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"477\" height=\"190\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-9.png\" alt=\"\" class=\"wp-image-105629\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-9.png 477w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-9-300x119.png 300w\" sizes=\"auto, (max-width: 477px) 100vw, 477px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-array-data-type-in-postgresql\"><a id=\"post-105620-_heading=h.3rdcrjn\"><\/a>ARRAY Data Type in PostgreSQL<\/h3>\n\n\n\n<p>PostgreSQL also allows you to store arrays of data in a single column. You can store multiple values of a single data type (like integers or text) within one array column. This is useful when you need to store lists of items related to a single row, without creating a separate table.<\/p>\n\n\n\n<p><strong>Example Use Case:<\/strong><\/p>\n\n\n\n<p>If you have a table of students and you want to store a list of the courses they&#8217;re enrolled in for each student, you could use an array to hold all the course names in one column. Here\u2019s how you can do this:<\/p>\n\n\n\n<p>Create a table and a courses column to hold an array of course names, such as &#8216;Math&#8217;, &#8216;History&#8217;, &#8216;Science&#8217;.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE students (\n    id SERIAL PRIMARY KEY,\n    name TEXT,\n    courses TEXT[]\n);<\/pre>\n\n\n\n<p>Insert data into the array, and then output the contents:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO students (name, courses) \nVALUES ('John Doe', ARRAY['Math', 'History', 'Science']);\n\nSELECT * FROM students;<\/pre>\n\n\n\n<p>The output would be (though the id value may be different):<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"418\" height=\"107\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-10.png\" alt=\"\" class=\"wp-image-105630\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-10.png 418w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-10-300x77.png 300w\" sizes=\"auto, (max-width: 418px) 100vw, 418px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This shows a list of the courses John Doe takes as a student.<\/p>\n\n\n\n<p>The main difference between an <code>`ENUM`<\/code> and an <code>`ARRAY`<\/code> is that an <code>`ENUM`<\/code> lets you pick just <strong>one<\/strong> value from a set list of options, while an <code>`ARRAY`<\/code> allows you to store<strong> any<\/strong> value of the same type (like a list) in a single column.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-bytea-data-type\"><a id=\"post-105620-_heading=h.26in1rg\"><\/a>BYTEA Data Type<\/h3>\n\n\n\n<p>Sometimes, applications may be required to store images that are uploaded by users, the <code>BYTEA<\/code> data type can help you do that.<\/p>\n\n\n\n<p>The BYTEA data type is used to store binary data, such as images or other non-text files. It can store binary data of up to 1GB, which is about 1024 MB in a single column<\/p>\n\n\n\n<p>PostgreSQL\u2019s BYTEA supports two ways to format this binary data: Hex format and Escape format. Hex format uses hexadecimal (hex) values, which are characters like 0-9 and A-F.<\/p>\n\n\n\n<p>Binary data in hex format looks cleaner and is often easier to understand, especially for data that could include special characters. For instance, the hex value for a small image file might start like this: \\x89504e47&#8230;.<\/p>\n\n\n\n<p>The escape format is an older style and is now less common, but it can still be used. In escape format, binary data is represented by escape sequences, using backslashes (\\) to mark special bytes. For instance, a byte might be shown as \\201.<\/p>\n\n\n\n<p>Here\u2019s an example on working with the BYTEA data type:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE messages (\n    id SERIAL PRIMARY KEY,       \n    message_data BYTEA           \n);<\/pre>\n\n\n\n<p>We will insert binary data in an hexadecimal format which represents the text &#8220;Hello!&#8221; into the <code>BYTEA<\/code><\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">INSERT INTO messages (message_data) \nVALUES (E'\\\\x48656C6C6F21');\n\nSELECT message_data FROM messages;<\/pre>\n\n\n\n<p>The output with be a binary value:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"214\" height=\"95\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-11.png\" alt=\"\" class=\"wp-image-105631\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>This is what the output looks like. You can use PostgreSQL&#8217;s convert_from() function to decode the binary data into a human-readable text format:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">SELECT convert_from(message_data, 'UTF8') AS readable_message <br>FROM messages;<\/pre>\n\n\n\n<p>Then the output would be:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"234\" height=\"95\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-12.png\" alt=\"\" class=\"wp-image-105632\"\/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>BYTEA is useful for many uses, but may not be the perfect choice when storing very large binary objects. PostgreSQL\u2019s <a href=\"https:\/\/www.postgresql.org\/docs\/current\/largeobjects.html\">large object<\/a> is often a better choice. Although the large object is not a data type, it is a bit similar to how the <code>BLOB<\/code> types in MYSQL work, but a bit more complicated to use. PostgreSQL\u2019s official documentation sheds more light on how to use the <a href=\"https:\/\/www.postgresql.org\/docs\/current\/lo-interfaces.html#LO-CREATE\">large object<\/a>.<\/p>\n\n\n\n<p>Let\u2019s take a look at a brief comparison of the BYTEA data type in PostgreSQL and the BLOB data types in MySQL:<a id=\"post-105620-_heading=h.lnxbz9\"><\/a><\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><br><p><strong>Feature<\/strong><\/p><br><\/td><td><br><p><strong>BLOB<\/strong><\/p><br><\/td><td><br><p><strong>BYTEA<\/strong><\/p><br><\/td><\/tr><tr><td>\n<p>Size Limit<\/p>\n<\/td><td>\n<p>It can store binary size greater than 1GB.<\/p>\n<\/td><td>\n<p>It has a maximum size of 1GB.<\/p>\n<\/td><\/tr><tr><td>\n<p>Ease of Use<\/p>\n<\/td><td>\n<p>To function properly, it requires the use of some APIs or special functions.<\/p>\n<\/td><td>\n<p>It is simple to use and works with standard SQL commands.<\/p>\n<\/td><\/tr><tr><td>\n<p>Use case<\/p>\n<\/td><td>\n<p>Best for large binary objects.<\/p>\n<\/td><td>\n<p>Better for smaller binary objects.<\/p>\n<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-mysql-vs-postgresql-comparison-of-string-data-types\">MySQL vs PostgreSQL: Comparison of String Data Types<\/h2>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td>\n<p><strong>Data Type <\/strong><\/p>\n<\/td><td>\n<p><strong>MySQL<\/strong><\/p>\n<\/td><td>\n<p><strong> Range (MySQL)<\/strong><\/p>\n<\/td><td>\n<p><strong>PostgreSQL<\/strong><\/p>\n<\/td><td>\n<p><strong>Range (PostgreSQL)<\/strong><\/p>\n<\/td><td>\n<p><strong>Differences<\/strong><\/p>\n<\/td><\/tr><tr><td>\n<p>String types<\/p>\n<\/td><td>\n<p>\u2018CHAR(n)\u2019, \u2019VARCHAR(n)\u2019<\/p>\n<\/td><td>\n<p>Maximum VARCHAR length: 65535<\/p>\n<p>Maximum CHAR length: 255<\/p>\n<\/td><td>\n<p>&#8216;CHARACTER(n)&#8217;, &#8216;CHARACTER VARYING(n)&#8217;, &#8216;CHAR(n)&#8217;, &#8216;BPCHAR(n)&#8217; &#8216;VARCHAR(n)&#8217;<\/p>\n<\/td><td>\n<p>Maximum CHARACTER VARYING(n) and VARCHAR(n) length: 10485760<\/p>\n<p>&#8216;CHARACTER(n)\u2019, \u2018CHAR(n)\u2019: 1GB<\/p>\n<\/td><td>\n<p>Fixed-length types (CHAR) can be faster but may waste space.<\/p>\n<p>Variable-length types (VARCHAR) are more storage-efficient.<\/p>\n<p>PostgreSQL&#8217;s CHARACTER and CHARACTER VARYING handle variable-length strings efficiently.<\/p>\n<\/td><\/tr><tr><td>\n<p>Text types<\/p>\n<\/td><td>\n<p>\u2018TINYTEXT\u2019, \u2018TEXT\u2019, \u2018MEDIUMTEXT\u2019, \u2018LONGTEXT\u2019<\/p>\n<\/td><td>\n<p>\u2018TINYTEXT\u2019 maximum length: 255(2<sup>8<\/sup>-1)<\/p>\n<p>\u2018TEXT\u2019 maximum length: 65,535<\/p>\n<p>\u2018MEDIUMTEXT\u2019 maximum length: 16,777,215<\/p>\n<p>\u2018LONGTEXT\u2019 maximum length: 4,294,967,295<\/p>\n<\/td><td>\n<p>\u2018TEXT\u2019<\/p>\n<\/td><td>\n<p>Maximum length: 1GB<\/p>\n<\/td><td>\n<p>MySQL provides multiple text types for different storage needs, while PostgreSQL uses a single TEXT type.<\/p>\n<\/td><\/tr><tr><td>\n<p>Binary types<\/p>\n<\/td><td>\n<p>\u2018BINARY\u2019, \u2018VARBINARY\u2019, \u2018TINYBLOB\u2019, \u2018BLOB\u2019, \u2018MEDIUMBLOB\u2019, \u2018LONGBLOB\u2019<\/p>\n<\/td><td>\n<p>BINARY: Fixed-length binary string up to 255 bytes.<\/p>\n<p>VARBINARY: Variable-length binary string up to 65,535 bytes.<\/p>\n<p>TINYBLOB: Binary large object up to 255 bytes.<\/p>\n<p>BLOB: Binary large object up to 65,535 bytes.<\/p>\n<p>MEDIUMBLOB: Binary large object up to 16,777,215 bytes (16 MB).<\/p>\n<p>LONGBLOB: Binary large object up to 4,294,967,295 bytes (4 GB).<\/p>\n<\/td><td>\n<p>\u2018BYTEA\u2019<\/p>\n<\/td><td>\n<p>Maximum limit: 1GB<\/p>\n<\/td><td>\n<p>MySQL offers various binary types while PostgreSQL uses only BYTEA for storing binary data.<\/p>\n<\/td><\/tr><tr><td>\n<p>Special types<\/p>\n<\/td><td>\n<p>\u2018ENUM\u2019, \u2018SET\u2019<\/p>\n<\/td><td>\n<p>Maximum length of ENUM: Defined by the enumeration.<\/p>\n<p>Maximum length of SET: 65,535 bytes<\/p>\n<\/td><td>\n<p>\u2018ENUM\u2019, \u2018ARRAY\u2019<\/p>\n<\/td><td>\n<p>Maximum length of ENUM: Defined by the enumeration.<\/p>\n<p>Maximum length of ARRAY: Defined by the array&#8217;s base type length.<\/p>\n<\/td><td>\n<p>Both databases support enumerated types (ENUM).<\/p>\n<p>PostgreSQL offers ARRAY, while MySQL provides SET.<\/p>\n<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-enum-mysql-vs-enum-postgresql\"><a id=\"post-105620-_heading=h.35nkun2\"><\/a>ENUM (MySQL) Vs. ENUM (PostgreSQL)<\/h3>\n\n\n\n<p>In MySQL and PostgreSQL, the ENUM type is used to define a column that can only hold one value from a specific list of values. However, the way ENUM is implemented in each database is a bit different. Let\u2019s take a look at how this works:<\/p>\n\n\n\n<p><strong>MySQL<\/strong><\/p>\n\n\n\n<p>In MySQL, you can define ENUM directly within the column definition when creating a table<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE orders (\n    order_id INT,\n    status ENUM('pending', 'shipped', 'delivered')\n);<\/pre>\n\n\n\n<p>Once defined, modifying the <code>ENUM<\/code> list (like adding new options) requires altering the table. MySQL does not allow direct changes to the <code>ENUM<\/code> changes, so here\u2019s how it supports adding new options:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ALTER TABLE orders \nMODIFY COLUMN status \n  ENUM('pending', 'shipped', 'delivered', 'canceled') NOT NULL;<\/pre>\n\n\n\n<p>Let\u2019s verify the changes using the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">DESCRIBE orders;<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"651\" height=\"121\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-13.png\" alt=\"\" class=\"wp-image-105633\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-13.png 651w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/02\/word-image-105620-13-300x56.png 300w\" sizes=\"auto, (max-width: 651px) 100vw, 651px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><strong>PostgreSQL<\/strong><\/p>\n\n\n\n<p>In PostgreSQL, <code>ENUM<\/code> is created as a separate data type before it can be used in a table. You first define the type, then use it in a column.<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TYPE order_status AS ENUM ('pending', 'shipped', 'delivered');<\/pre>\n\n\n\n<p>Then you can use the <code>ENUM<\/code> this way:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">CREATE TABLE orders (\n    order_id INT,\n    status order_status\n);<\/pre>\n\n\n\n<p>PostgreSQL allows you to add new values to the <code>ENUM<\/code> type with a simple command<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ALTER TYPE order_status ADD VALUE 'returned';<\/pre>\n\n\n\n<p>This means PostgreSQL is slightly more flexible when modifying <code>ENUM<\/code> values. Note however, that removing an ENUM value is not supported, so you will have to remove the ENUM and replace it (while taking care to not lose data. For more information, <a href=\"https:\/\/stackoverflow.com\/questions\/25811017\/how-to-delete-an-enum-type-value-in-postgres\">this StackOverflow thread<\/a> covers it quite well)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-set-mysql-vs-array-postgresql\"><a id=\"post-105620-_heading=h.1ksv4uv\"><\/a>SET(MySQL) Vs. ARRAY(PostgreSQL)<\/h3>\n\n\n\n<p>In MySQL and PostgreSQL, <code>SET<\/code> and <code>ARRAY<\/code> data types both allow you to store multiple values in a single column, but they work differently:<\/p>\n\n\n\n<p>MySQL&#8217;s <code>`SET`<\/code> type stores multiple predefined options you specify in advance, so each stored value must come from this fixed list. On the other hand, PostgreSQL&#8217;s <code>`ARRAY`<\/code> type stores multiple values without a fixed list, allowing you to add any values of the same data type without restrictions.<\/p>\n\n\n\n<p>If you want to add or remove options in your <code>SET<\/code>, you have to change the column setup in the database but in PostgreSQL\u2019s <code>ARRAY<\/code>, you can add or remove values as needed without having to adjust the structure of the database column.<\/p>\n\n\n\n<p>MySQL\u2019s <code>SET<\/code> works well when you have a small, fixed list of choices, like &#8220;small,&#8221; &#8220;medium,&#8221; &#8220;large while PostgreSQL\u2019s <code>ARRAY<\/code> is useful for storing a list of values that may change frequently, like a list of tags or categories that can vary.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-key-takeaways\"><a id=\"post-105620-_heading=h.sktcpuo5gs70\"><\/a>Key Takeaways<\/h2>\n\n\n\n<p>MySQL offers fixed-length (<code>CHAR<\/code>) and variable-length (<code>VARCHAR<\/code>) types, with a simpler range but clear limits, while PostgreSQL provides more flexibility with <code>CHARACTER<\/code>, <code>CHARACTER<\/code> <code>VARYING<\/code>, and related options. PostgreSQL&#8217;s string handling is more robust, with larger size limits (up to 1GB for <code>CHAR<\/code> and 10MB+ for <code>VARCHAR<\/code>), making it better for large or complex datasets.<\/p>\n\n\n\n<p>MySQL breaks down text storage into multiple types (<code>TINYTEXT<\/code>, <code>TEXT<\/code>, <code>MEDIUMTEXT<\/code>, <code>LONGTEXT<\/code>), offering granular control over storage size. PostgreSQL simplifies this with a single <code>TEXT<\/code> type, which can handle data up to 1GB. This simplicity makes PostgreSQL&#8217;s approach cleaner and easier to manage for text-heavy applications.<\/p>\n\n\n\n<p>MySQL provides a variety of binary storage types (<code>BLOB<\/code>, <code>VARBINARY<\/code>, <code>TINYBLOB<\/code>, etc.), allowing for optimized storage of binary data of different sizes. PostgreSQL, on the other hand, uses just one type (<code>BYTEA<\/code>), which is straightforward but highly capable, with a maximum size of 1GB.<\/p>\n\n\n\n<p>Both databases support enumerated types (<code>ENUM<\/code>), but PostgreSQL also includes arrays (<code>ARRAY<\/code>), while MySQL offers sets (SET). PostgreSQL\u2019s <code>ARRAY<\/code> provides more advanced data structuring, whereas MySQL\u2019s <code>SET<\/code> is a simpler solution for predefined collections.<\/p>\n\n\n\n<p>Choose MySQL if you prefer a variety of types tailored for specific storage needs, especially for applications that benefit from granular control. Choose PostgreSQL if you need more flexibility, simplicity in managing text data, or advanced features like arrays and larger size limits.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A very common task in creating a database is to store string data. For example, words, paragraph(s) or even documents. String data types allow you to do just that and store and represent text. They handle everything from simple names and addresses to complex data. A string is simply a sequence of characters. These characters&#8230;&hellip;<\/p>\n","protected":false},"author":341597,"featured_media":105636,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,145792,143534],"tags":[159268,5854,158978],"coauthors":[158988],"class_list":["post-105620","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-featured","category-mysql","category-postgresql","tag-aishabukar_mysql_postgresql","tag-mysql","tag-postgresql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/105620","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/341597"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=105620"}],"version-history":[{"count":5,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/105620\/revisions"}],"predecessor-version":[{"id":105644,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/105620\/revisions\/105644"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/105636"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=105620"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=105620"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=105620"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=105620"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}