{"id":34685,"date":"2024-05-08T11:23:36","date_gmt":"2024-05-08T01:23:36","guid":{"rendered":"https:\/\/database.guide\/?p=34685"},"modified":"2024-06-08T10:48:01","modified_gmt":"2024-06-08T00:48:01","slug":"understanding-arrays-in-postgresql","status":"publish","type":"post","link":"https:\/\/database.guide\/understanding-arrays-in-postgresql\/","title":{"rendered":"Understanding Arrays in PostgreSQL"},"content":{"rendered":"\n<p class=\"\">In PostgreSQL we have the ability to create variable-length multidimensional arrays and define columns as array types.<\/p>\n\n\n\n<p class=\"\">Here&#8217;s a quick overview of PostgreSQL arrays.<\/p>\n\n\n\n<!--more-->\n\n\n\n<h2 class=\"wp-block-heading\">Creating an Array Column<\/h2>\n\n\n\n<p class=\"\">We have a few options when it comes to creating a column with an array type in PostgreSQL. Regardless of which method we use, we need to specify the data type of the elements within the array.<\/p>\n\n\n\n<p class=\"\">We don&#8217;t use the keyword <code>array<\/code> in the same fashion that we do when defining other types.<\/p>\n\n\n\n<p class=\"\">One way to define a column as an array is to append square brackets (<code>[]<\/code>) to the data type name of the array elements.<\/p>\n\n\n\n<p class=\"\">Here&#8217;s an example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE array_test(\n    c1 integer&#91;],\n    c2 text&#91;],\n    c3 integer&#91;]&#91;]\n);<\/code><\/pre>\n\n\n\n<p class=\"\">That code creates a table with three columns. All three columns are defined as array types. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li class=\"\">The <code>c1<\/code> column is a single dimensional integer array, which means it accepts an array of integer values. We know it&#8217;s an array type because we appended square brackets to the data type name. And we know it&#8217;s single dimensional because it only has one pair of square brackets.<\/li>\n\n\n\n<li class=\"\">The <code>c2<\/code> column is a single dimensional text array. <\/li>\n\n\n\n<li class=\"\">The <code>c3<\/code> array is a multi dimensional integer array. It&#8217;s multi dimensional because we included more than one pair of square brackets. In this case there are two sets of square brackets, so it&#8217;s a two dimensional array.<\/li>\n<\/ul>\n\n\n\n<p class=\"\">At the time of writing, PostgreSQL 16.2 does not enforce the number of dimensions. So we could insert say, a two dimensional array into our <code>c1<\/code> column, or a one dimensional array into the <code>c3<\/code> column for example.<\/p>\n\n\n\n<p class=\"\">It&#8217;s possible to specify the array size, but PostgreSQL basically ignores this (at least as of PostgreSQL 16 at the time of writing). So we could do the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE array_test_2(\n    c1 integer&#91;3],\n    c2 text&#91;4],\n    c3 integer&#91;3]&#91;2]\n);<\/code><\/pre>\n\n\n\n<p class=\"\">But as alluded to, PostgreSQL does not enforce any such size restrictions. However, arrays must be rectangular. Therefore, all sub-arrays at the same level must be of the same dimensions.<\/p>\n\n\n\n<p class=\"\">We can also use the <code>ARRAY<\/code> keyword to define a column as a one dimensional array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CREATE TABLE array_test_3(\n    c1 integer ARRAY,\n    c2 text ARRAY&#91;4],\n    c3 integer ARRAY\n);<\/code><\/pre>\n\n\n\n<p class=\"\">We have the option of specifying the array size by appending square brackets to the <code>ARRAY<\/code> keyword (as seen in the definition for <code>c2<\/code>) but again, such size limits are not enforced by PostgreSQL.<\/p>\n\n\n\n<p class=\"\">Using the <code>ARRAY<\/code> keyword helps keep the code compliant with the SQL standard, but is entirely optional.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Inserting an Array<\/h2>\n\n\n\n<p class=\"\">Once we&#8217;ve created a table or column that accepts an array type, we can go ahead and insert an array into it.<\/p>\n\n\n\n<p class=\"\">One way to insert an array is to provide it as a literal constant:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>INSERT INTO array_test VALUES \n    (\n        '{ 1,2,3 }',\n        '{ \"Cat\", \"Dog\", \"Horse\", \"Bear\", \"Duck\" }',\n        '{ {1,2,3}, {4,5,6}, {7,8,9} }'\n    );<\/code><\/pre>\n\n\n\n<p class=\"\">Here, all three arrays are provided as a literal constant. These are provided in the format specified by the following syntax:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>'{ val1 delim val2 delim ... }'<\/code><\/pre>\n\n\n\n<p class=\"\">Here, <em><code>delim<\/code><\/em> is the delimiter character for the type. This delimiter is stored in the <code>pg_type<\/code> catalog. Most of the standard data types use a comma (<code>,<\/code>), but the <code>box<\/code> type uses a semicolon (<code>;<\/code>). <\/p>\n\n\n\n<p class=\"\">Each <em><code>val<\/code><\/em> is either a constant of the array element type, or a subarray.<\/p>\n\n\n\n<p class=\"\">Another way to insert an array is with the <a href=\"https:\/\/database.guide\/understanding-the-array-constructor-in-postgresql\/\" data-type=\"post\" data-id=\"35582\"><code>ARRAY<\/code> constructor<\/a>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>INSERT INTO array_test VALUES \n    (\n        ARRAY&#91; 41, 52, 67 ],\n        ARRAY&#91; 'Zebra', 'Bird', 'Mouse', 'Cow', 'Pig' ],\n        ARRAY&#91; ARRAY&#91; 32, 78, 14 ], ARRAY&#91; 102, 99, 37 ], ARRAY&#91; 18, 65, 29 ] ]\n    );<\/code><\/pre>\n\n\n\n<p class=\"\">We can also use the <code>ARRAY<\/code> constructor by itself to create an array on the fly:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT ARRAY&#91; 1,2,3 ];<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  array  <br>---------<br> {1,2,3}<\/pre>\n\n\n\n<p class=\"\">As mentioned, all sub-arrays at the same level must have the same dimensions. Therefore, we can do this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT ARRAY&#91; ARRAY&#91;1,2,3], ARRAY&#91;4,5,6] ];<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">       array       <br>-------------------<br> {{1,2,3},{4,5,6}}<\/pre>\n\n\n\n<p class=\"\">But we can&#8217;t do this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT ARRAY&#91; ARRAY&#91;1,2,3], ARRAY&#91;4,5] ];<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ERROR:  multidimensional arrays must have array expressions with matching dimensions<\/pre>\n\n\n\n<p class=\"\">Here, the outer array contains two inner arrays. The first one is defined as having three elements but the second has two. This is a &#8220;no no&#8221;, and we got an error accordingly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Selecting an Array<\/h2>\n\n\n\n<p class=\"\">Let&#8217;s return all data from our table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |             c2             |                 c3                  <br>------------+----------------------------+-------------------------------------<br> {1,2,3}    | {Cat,Dog,Horse,Bear,Duck}  | {{1,2,3},{4,5,6},{7,8,9}}<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig} | {{32,78,14},{102,99,37},{18,65,29}}<\/pre>\n\n\n\n<p class=\"\">As expected, the rows reflect the data that we inserted.<\/p>\n\n\n\n<p class=\"\">We can return any of these arrays by simply including that column in our <code>SELECT<\/code> list:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2 FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">             c2             <br>----------------------------<br> {Cat,Dog,Horse,Bear,Duck}<br> {Zebra,Bird,Mouse,Cow,Pig}<\/pre>\n\n\n\n<p class=\"\">In this case we returned the arrays in the <code>c2<\/code> column. We didn&#8217;t narrow it down with a <code>WHERE<\/code> clause or anything, so all rows were returned.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Selecting Array Elements<\/h2>\n\n\n\n<p class=\"\">We can select specific elements by specifying the element index within square brackets.<\/p>\n\n\n\n<p class=\"\">Here&#8217;s an example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2&#91;1] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  c2   <br>-------<br> Cat<br> Zebra<\/pre>\n\n\n\n<p class=\"\">Array subscripts start at 1 by default, and so <code>c2[1]<\/code> returns the first element of the array. <\/p>\n\n\n\n<p class=\"\">We can also use this syntax in a <code>WHERE<\/code> clause to narrow the results down:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2 FROM array_test \nWHERE c1&#91;1] = 41;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">             c2             <br>----------------------------<br> {Zebra,Bird,Mouse,Cow,Pig}<\/pre>\n\n\n\n<p class=\"\">In the above example we returned the whole array, but we can also return individual elements from within that array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2&#91;1] FROM array_test \nWHERE c1&#91;1] = 41; <\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  c2   <br>-------<br> Zebra<\/pre>\n\n\n\n<p class=\"\">We can access elements from multi dimensional arrays by using multiple sets of square brackets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c3&#91;2]&#91;3] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> c3 <br>----<br>  6<br> 37<\/pre>\n\n\n\n<p class=\"\">In this case we retrieved the third element of the second array in the <code>c3<\/code> column.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Returning Slices from Arrays<\/h2>\n\n\n\n<p class=\"\">We can return parts of an array by using a syntax that specifies the lower bound and the upper bound for the elements. This is written with a colon syntax, where the lower bound and upper bound is separated by a colon.<\/p>\n\n\n\n<p class=\"\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2&#91;2:4] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">        c2        <br>------------------<br> {Dog,Horse,Bear}<br> {Bird,Mouse,Cow}<\/pre>\n\n\n\n<p class=\"\">Here we extracted the second, third and fourth elements of each array.<\/p>\n\n\n\n<p class=\"\">We can leave the lower or upper bound open, so that it returns all prior or subsequent elements from the given point. For example, if we omit our upper bound of 4, we get the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2&#91;2:] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">          c2           <br>-----------------------<br> {Dog,Horse,Bear,Duck}<br> {Bird,Mouse,Cow,Pig}<\/pre>\n\n\n\n<p class=\"\">This time it returned all elements from the second one to the end of the array.<\/p>\n\n\n\n<p class=\"\">We can do a similar thing to get all elements from the start of the array up to a certain point:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c2&#91;:2] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">      c2      <br>--------------<br> {Cat,Dog}<br> {Zebra,Bird}<\/pre>\n\n\n\n<p class=\"\">This time we got all elements up to the second element.<\/p>\n\n\n\n<p class=\"\">On multi dimensional arrays we can use multiple pairs of square brackets:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c3&#91;1:2]&#91;2:3] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">        c3         <br>-------------------<br> {{2,3},{5,6}}<br> {{78,14},{99,37}}<\/pre>\n\n\n\n<p class=\"\">In this case I got the second and third elements of the first two arrays in the array at <code>c3<\/code>.<\/p>\n\n\n\n<p class=\"\">Note that if any dimension is written as a slice (i.e. using the colon syntax) then all dimensions are treated as slices, even if not all of them are written as a slice (i.e. no colon). Therefore we could write the following:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT c3&#91;1:2]&#91;3] FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">            c3            <br>--------------------------<br> {{1,2,3},{4,5,6}}<br> {{32,78,14},{102,99,37}}<\/pre>\n\n\n\n<p class=\"\">Here, we only included a colon in the first pair of square brackets but not the second. Any dimension that doesn&#8217;t contain a colon is treated as starting from 1 and ending at the specified number. Therefore in our example, the <code>[3]<\/code> part meant that it started at the first element and ended at the third.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get the Array&#8217;s Dimension<\/h2>\n\n\n\n<p class=\"\">We can use the <a href=\"https:\/\/database.guide\/understanding-array_dims-in-postgresql\/\" data-type=\"post\" data-id=\"35817\"><code>array_dims()<\/code> function<\/a> to return the dimension of a given array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT array_dims(c3) FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> array_dims <br>------------<br> [1:3][1:3]<br> [1:3][1:3]<\/pre>\n\n\n\n<p class=\"\">Here it is across all columns:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT \n    array_dims(c1) AS c1, \n    array_dims(c2) AS c2, \n    array_dims(c3) AS c3 \nFROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">  c1   |  c2   |     c3     <br>-------+-------+------------<br> [1:3] | [1:5] | [1:3][1:3]<br> [1:3] | [1:5] | [1:3][1:3]<\/pre>\n\n\n\n<p class=\"\">Another way to do it is with the <code><a href=\"https:\/\/database.guide\/understanding-the-array_upper-function-in-postgresql\/\" data-type=\"post\" data-id=\"35846\">array_upper()<\/a><\/code> and <code><a href=\"https:\/\/database.guide\/a-quick-intro-to-the-array_lower-function-in-postgresql\/\" data-type=\"post\" data-id=\"35852\">array_lower()<\/a><\/code> functions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT \n    array_lower(c3, 2) AS lower, \n    array_upper(c3, 2) AS upper\nFROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> lower | upper <br>-------+-------<br>     1 |     3<br>     1 |     3<\/pre>\n\n\n\n<p class=\"\">That returned the upper and lower bounds for the second dimension of the <code>c3<\/code> array. <\/p>\n\n\n\n<p class=\"\">The <code>array_upper()<\/code> and <code>array_lower()<\/code> functions return an integer whereas <code>array_dims()<\/code> returns text. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get the Array&#8217;s Cardinality<\/h2>\n\n\n\n<p class=\"\">We can use the <code>cardinality()<\/code> function to return the total number of elements in an array across all dimensions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT cardinality(c3) FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> cardinality <br>-------------<br>           9<br>           9<\/pre>\n\n\n\n<p class=\"\">Here we can see that the function returned the total number of elements across the arrays at <code>c3<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Search an Array<\/h2>\n\n\n\n<p class=\"\">Previously we selected the value from a given index of an array. But we also have the option of searching through the whole array for a given value. <\/p>\n\n\n\n<p class=\"\">One way to do this is with the <code>ANY()<\/code> construct:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM array_test \nWHERE 'Horse' = ANY(c2);<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">   c1    |            c2             |            c3             <br>---------+---------------------------+---------------------------<br> {1,2,3} | {Cat,Dog,Horse,Bear,Duck} | {{1,2,3},{4,5,6},{7,8,9}}<\/pre>\n\n\n\n<p class=\"\">We can also use <code>SOME()<\/code>, which is a synonym for <code>ANY()<\/code>. So the following produces the same result:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM array_test \nWHERE 'Horse' = SOME(c2);<\/code><\/pre>\n\n\n\n<p class=\"\">Another way to search through an array is to use the <code>ALL()<\/code> construct:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM array_test \nWHERE 40 &lt; ALL(c1);<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |             c2             |                 c3                  <br>------------+----------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig} | {{32,78,14},{102,99,37},{18,65,29}}<\/pre>\n\n\n\n<p class=\"\">In this case all elements of <code>c1<\/code> are greater than 40 on the second row, and so <code>ALL()<\/code> returns <code>true<\/code> for that row, which results in the row being returned.<\/p>\n\n\n\n<p class=\"\">Another tool we have for searching arrays is the <code>&amp;&amp;<\/code> operator:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM array_test \nWHERE c2 &amp;&amp; ARRAY&#91;'Mouse'];<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |             c2             |                 c3                  <br>------------+----------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig} | {{32,78,14},{102,99,37},{18,65,29}}<\/pre>\n\n\n\n<p class=\"\">The <code>&amp;&amp;<\/code> operator looks for an overlap between two arrays.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get the Position of a Value in an Array<\/h2>\n\n\n\n<p class=\"\">We can use <code>array_position()<\/code> and <code>array_positions()<\/code> to get the position of a given value within an array. <\/p>\n\n\n\n<p class=\"\">The <code>array_position()<\/code> function returns the first occurrence of the value in the array, whereas <code>array_positions()<\/code> returns all positions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT \n    array_position(ARRAY&#91; 'Cat', 'Dog', 'Cat', 'Horse', 'Cat' ], 'Cat'),\n    array_positions(ARRAY&#91; 'Cat', 'Dog', 'Cat', 'Horse', 'Cat' ], 'Cat');<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> array_position | array_positions <br>----------------+-----------------<br>              1 | {1,3,5}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Replace an Array<\/h2>\n\n\n\n<p class=\"\">We can replace an array in full by using the literal constant:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2 = '{\"a\", \"b\", \"c\", \"d\", \"e\"}'\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test; <\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |             c2             |                 c3                  <br>------------+----------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig} | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {a,b,c,d,e}                | {{1,2,3},{4,5,6},{7,8,9}}<\/pre>\n\n\n\n<p class=\"\">Or by using the <code>ARRAY<\/code> constructor:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2 = ARRAY&#91;'Rabbit', 'Rat', 'Cheetah', 'Lion', 'Leopard']\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test; <\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |                c2                 |                 c3                  <br>------------+-----------------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig}        | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {Rabbit,Rat,Cheetah,Lion,Leopard} | {{1,2,3},{4,5,6},{7,8,9}}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Update an Array Element<\/h2>\n\n\n\n<p class=\"\">We can update a specific array element by referencing its index:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2&#91;2] = 'Squirrel'\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |                   c2                   |                 c3                  <br>------------+----------------------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig}             | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {Rabbit,Squirrel,Cheetah,Lion,Leopard} | {{1,2,3},{4,5,6},{7,8,9}}<\/pre>\n\n\n\n<p class=\"\">And here it is updating a multi dimensional array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c3&#91;2]&#91;3] = 66\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |                   c2                   |                 c3                  <br>------------+----------------------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig}             | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {Rabbit,Squirrel,Cheetah,Lion,Leopard} | {{1,2,3},{4,5,66},{7,8,9}}<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Update a Whole Slice<\/h2>\n\n\n\n<p class=\"\">We can update a whole slice like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2&#91;2:4] = '{\"Cat\",\"Dog\",\"Cow\"}'\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |              c2              |                 c3                  <br>------------+------------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig}   | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {Rabbit,Cat,Dog,Cow,Leopard} | {{1,2,3},{4,5,66},{7,8,9}}<\/pre>\n\n\n\n<p class=\"\"> We can also leave one of the bounds open in order to update all remaining or preceding elements. For example, the following updates all elements from the fourth subscript:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2&#91;4:] = '{\"Buffalo\",\"Ant\"}'\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |              c2              |                 c3                  <br>------------+------------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig}   | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {Rabbit,Cat,Dog,Buffalo,Ant} | {{1,2,3},{4,5,66},{7,8,9}}<\/pre>\n\n\n\n<p class=\"\">Here&#8217;s what happens if we provide too many values:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2&#91;4:] = '{\"Monkey\",\"Moth\",\"Butterfly\"}'\nWHERE c1 = '{1,2,3}';\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |              c2              |                 c3                  <br>------------+------------------------------+-------------------------------------<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig}   | {{32,78,14},{102,99,37},{18,65,29}}<br> {1,2,3}    | {Rabbit,Cat,Dog,Monkey,Moth} | {{1,2,3},{4,5,66},{7,8,9}}<\/pre>\n\n\n\n<p class=\"\">Only the remaining elements were updated. So in our case, the first two elements (<code>Monkey<\/code> and <code>Moth<\/code>) made their way on to the array, but the third one (<code>Butterfly<\/code>) didn&#8217;t.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Enlarge an Array<\/h2>\n\n\n\n<p class=\"\">We can enlarge an array by assigning an element to an index that doesn&#8217;t currently exist:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>UPDATE array_test \nSET c2&#91;7] = 'Swan'\nWHERE c1 = '{41,52,67}';\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">     c1     |                  c2                  |                 c3                  <br>------------+--------------------------------------+-------------------------------------<br> {1,2,3}    | {Rabbit,Cat,Dog,Monkey,Moth}         | {{1,2,3},{4,5,66},{7,8,9}}<br> {41,52,67} | {Zebra,Bird,Mouse,Cow,Pig,NULL,Swan} | {{32,78,14},{102,99,37},{18,65,29}}<\/pre>\n\n\n\n<p class=\"\">When we do this, any positions between existing elements and the specified one\/s will be set to <code>NULL<\/code>. We can see this in our example. I specified that <code>Swan<\/code> should be inserted into the 7th position, but there were previously only 5 positions. Therefore, the 6th position was filled with <code>NULL<\/code> in order to get <code>Swan<\/code> to the 7th position.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Specify the Lower Bound of an Array<\/h2>\n\n\n\n<p class=\"\">By default, the lower bound of an array is 1. This means that the first element starts at 1, the second starts at 2, and so on.<\/p>\n\n\n\n<p class=\"\">But we do have the option of changing this. <\/p>\n\n\n\n<p class=\"\">We can use subscript assignment to specify the subscript for the array. We can do this by prepending the array with the subscript ranges enclosed in square brackets, with the dimensions separated by a colon.<\/p>\n\n\n\n<p class=\"\">Example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT ('&#91;0:2]={ \"Cat\", \"Dog\", \"Horse\" }'::text&#91;])&#91;0];<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\"> text <br>------<br> Cat<\/pre>\n\n\n\n<p class=\"\">In this example I created a zero based array. In other words, the subscripts start at zero. <\/p>\n\n\n\n<p class=\"\">Therefore, in order to get the first item, we need to use <code>0<\/code> instead of <code>1<\/code>. That&#8217;s exactly what we did here. We used <code>[0]<\/code> to return the first item in the array, which was <code>Cat<\/code>.<\/p>\n\n\n\n<p class=\"\">We can use this approach when inserting data into a table:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>INSERT INTO array_test VALUES \n    (\n        '&#91;0:2]={ 8,7,9 }',\n        '&#91;-5:-1]={ \"Gecko\", \"Agra\", \"Badger\", \"Beaver\", \"Platypus\" }',\n        '&#91;1:3]&#91;10:12]={ {45,78,13}, {14,53,31}, {98,26,27} }'\n    );\n\nSELECT * FROM array_test;<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">      c1       |                     c2                      |                       c3                        <br>---------------+---------------------------------------------+-------------------------------------------------<br> {1,2,3}       | {Rabbit,Cat,Dog,Monkey,Moth}                | {{1,2,3},{4,5,66},{7,8,9}}<br> {41,52,67}    | {Zebra,Bird,Mouse,Cow,Pig,NULL,Swan}        | {{32,78,14},{102,99,37},{18,65,29}}<br> [0:2]={8,7,9} | [-5:-1]={Gecko,Agra,Badger,Beaver,Platypus} | [1:3][10:12]={{45,78,13},{14,53,31},{98,26,27}}<\/pre>\n\n\n\n<p class=\"\">We can see that the arrays are inserted along with their respective subscript assignments.<\/p>\n\n\n\n<p class=\"\">We can reference the array elements by using the subscript based on the specified assignment. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT * FROM array_test\nWHERE c2&#91;-3] = 'Badger';<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">      c1       |                     c2                      |                       c3                        <br>---------------+---------------------------------------------+-------------------------------------------------<br> [0:2]={8,7,9} | [-5:-1]={Gecko,Agra,Badger,Beaver,Platypus} | [1:3][10:12]={{45,78,13},{14,53,31},{98,26,27}}<\/pre>\n\n\n\n<p class=\"\">In this case Badger is at <code>-3<\/code>, and that&#8217;s what I specified in my query. If this was a normal one-based array, then we would have needed to specify <code>3<\/code> instead of <code>-3<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Push a Value to an Array<\/h2>\n\n\n\n<p class=\"\">We can push new values to an array by concatenating the value with the array:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT ARRAY&#91;1,2,3] || ARRAY&#91;4,5,6];<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{1,2,3,4,5,6}<\/pre>\n\n\n\n<p class=\"\">Here&#8217;s an example that prepends and appends a value to an array from the database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\\x\nSELECT \n    c2 AS Original,\n    c2 || ARRAY&#91;'Horse'] AS Appended,\n    ARRAY&#91;'Horse'] || c2 AS Prepended\nFROM array_test\nWHERE c1 = '{ 1,2,3 }';<\/code><\/pre>\n\n\n\n<p class=\"\">Result (using vertical output):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">original  | {Rabbit,Cat,Dog,Monkey,Moth}<br>appended  | {Rabbit,Cat,Dog,Monkey,Moth,Horse}<br>prepended | {Horse,Rabbit,Cat,Dog,Monkey,Moth}<\/pre>\n\n\n\n<p class=\"\">For this example I used <code>psql<\/code>&#8216;s <code>\\x<\/code> meta command to change the results to expanded display to make the results easier to read without scrolling.<\/p>\n\n\n\n<p class=\"\">We can also use the <code><a href=\"https:\/\/database.guide\/how-array_prepend-works-in-postgresql\/\" data-type=\"post\" data-id=\"36222\">array_prepend()<\/a><\/code>, <code><a href=\"https:\/\/database.guide\/a-quick-look-at-array_append-in-postgresql\/\" data-type=\"post\" data-id=\"36216\">array_append()<\/a><\/code>, and <code><a href=\"https:\/\/database.guide\/a-quick-intro-to-array_cat-in-postgresql\/\" data-type=\"post\" data-id=\"36229\">array_cat()<\/a><\/code> functions to prepend and append values to arrays:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT \n    c2 AS Original,\n    array_append(c2, 'Horse') AS Appended,\n    array_prepend('Horse', c2) AS Prepended,\n    array_cat(c2, ARRAY&#91;'Horse']) AS \"Appended with array_cat\",\n    array_cat(ARRAY&#91;'Horse'], c2) AS \"Prepended with array_cat\"\nFROM array_test\nWHERE c1 = '{ 1,2,3 }';<\/code><\/pre>\n\n\n\n<p class=\"\">Result (using vertical output):<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">original                 | {Rabbit,Cat,Dog,Monkey,Moth}<br>appended                 | {Rabbit,Cat,Dog,Monkey,Moth,Horse}<br>prepended                | {Horse,Rabbit,Cat,Dog,Monkey,Moth}<br>Appended with array_cat  | {Rabbit,Cat,Dog,Monkey,Moth,Horse}<br>Prepended with array_cat | {Horse,Rabbit,Cat,Dog,Monkey,Moth}<\/pre>\n\n\n\n<p class=\"\">The <code>array_cat()<\/code> function can be used with multi dimensional arrays, but the other two can&#8217;t.<\/p>\n\n\n\n<p class=\"\">Here&#8217;s an example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT array_cat(ARRAY&#91;&#91;1,2],&#91;3,4]], ARRAY&#91;5,6]);<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">{{1,2},{3,4},{5,6}}<\/pre>\n\n\n\n<p class=\"\">And here&#8217;s one using an array from the database:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>SELECT \n    c3,\n    array_cat( c3, ARRAY&#91;10,11,12] )\nFROM array_test\nWHERE c1 = '{1,2,3}';<\/code><\/pre>\n\n\n\n<p class=\"\">Result:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">             c3             |               array_cat               <br>----------------------------+---------------------------------------<br> {{1,2,3},{4,5,66},{7,8,9}} | {{1,2,3},{4,5,66},{7,8,9},{10,11,12}}<\/pre>\n\n\n\n<p class=\"\"><\/p>\n\n\n\n<p class=\"\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In PostgreSQL we have the ability to create variable-length multidimensional arrays and define columns as array types. Here&#8217;s a quick overview of PostgreSQL arrays.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[40],"tags":[169,91,20],"class_list":["post-34685","post","type-post","status-publish","format-standard","hentry","category-postgresql","tag-arrays","tag-data-types","tag-what-is"],"_links":{"self":[{"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/posts\/34685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/comments?post=34685"}],"version-history":[{"count":5,"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/posts\/34685\/revisions"}],"predecessor-version":[{"id":36357,"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/posts\/34685\/revisions\/36357"}],"wp:attachment":[{"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/media?parent=34685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/categories?post=34685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/database.guide\/wp-json\/wp\/v2\/tags?post=34685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}