PostgreSQL Array Types
Introduction
PostgreSQL offers a powerful feature that many other relational databases lack: the ability to store arrays as values in a column. This means you can store multiple values of the same type in a single database field, rather than having to create separate tables or use other workarounds.
Arrays in PostgreSQL can be especially useful when:
- You need to store multiple values that logically belong together
- You want to avoid complex join operations for simple multi-value scenarios
- You're working with data that naturally comes in sets or lists
In this tutorial, we'll explore how to create, manipulate, and query array data types in PostgreSQL.
Creating Tables with Array Columns
To define a column as an array, you add square brackets []
after the data type:
CREATE TABLE inventory (
id SERIAL PRIMARY KEY,
product_name VARCHAR(100),
sizes TEXT[],
prices NUMERIC[]
);
This creates a table with two array columns: sizes
as a text array and prices
as a numeric array.
Inserting Data into Arrays
There are several ways to insert data into array columns:
Using Curly Braces Syntax
INSERT INTO inventory (product_name, sizes, prices)
VALUES ('T-shirt', '{"Small", "Medium", "Large", "XL"}', '{19.99, 19.99, 22.99, 24.99}');
Using Array Constructor
INSERT INTO inventory (product_name, sizes, prices)
VALUES ('Jeans', ARRAY['32x30', '32x32', '34x32', '36x32'], ARRAY[49.99, 49.99, 54.99, 54.99]);
Accessing Array Elements
PostgreSQL uses 1-based indexing for arrays (unlike many programming languages that use 0-based indexing).
Accessing a Single Element
SELECT product_name, sizes[1], prices[1]
FROM inventory;
Output:
product_name | sizes[1] | prices[1]
--------------+----------+-----------
T-shirt | Small | 19.99
Jeans | 32x30 | 49.99
Accessing a Range of Elements (Slicing)
You can also retrieve a slice of an array using the syntax array[start:end]
:
SELECT product_name, sizes[1:2], prices[3:4]
FROM inventory;
Output:
product_name | sizes[1:2] | prices[3:4]
--------------+-----------------+---------------
T-shirt | {Small,Medium} | {22.99,24.99}
Jeans | {32x30,32x32} | {54.99,54.99}
Modifying Arrays
Updating an Entire Array
UPDATE inventory
SET sizes = ARRAY['S', 'M', 'L', 'XL', 'XXL']
WHERE product_name = 'T-shirt';
Updating a Specific Element
UPDATE inventory
SET prices[5] = 26.99
WHERE product_name = 'T-shirt';
Appending to an Array
To add elements to an existing array, you can use the concatenation operator ||
:
UPDATE inventory
SET sizes = sizes || ARRAY['XXXL']
WHERE product_name = 'T-shirt';
Querying Arrays
PostgreSQL provides powerful operators for working with arrays.
ANY Operator: Check if a Value Exists in an Array
SELECT product_name, sizes
FROM inventory
WHERE 'L' = ANY(sizes);
This returns products that have the size 'L' available.
ALL Operator: Check if All Array Elements Match a Condition
SELECT product_name, prices
FROM inventory
WHERE 50.00 > ALL(prices);
This returns products where all prices are less than $50.00.
Array Contains Operator: @>
Check if one array contains another:
SELECT product_name
FROM inventory
WHERE sizes @> ARRAY['M', 'L'];
This returns products that have both 'M' and 'L' sizes available.
Array Length
Count the number of elements:
SELECT product_name, array_length(sizes, 1) as size_count
FROM inventory;
Output:
product_name | size_count
--------------+------------
T-shirt | 6
Jeans | 4
Array Functions
PostgreSQL provides various functions for working with arrays:
array_append and array_prepend
-- Add to the end
SELECT array_append(ARRAY[1, 2, 3], 4); -- Result: {1,2,3,4}
-- Add to the beginning
SELECT array_prepend(0, ARRAY[1, 2, 3]); -- Result: {0,1,2,3}
array_remove
SELECT array_remove(ARRAY[1, 2, 3, 2], 2); -- Result: {1,3}
unnest: Converting Arrays to Rows
This is particularly useful for working with arrays in queries:
SELECT product_name, unnest(sizes) as size, unnest(prices) as price
FROM inventory;
Output:
product_name | size | price
--------------+-------+-------
T-shirt | S | 19.99
T-shirt | M | 19.99
T-shirt | L | 22.99
T-shirt | XL | 24.99
T-shirt | XXL | 26.99
T-shirt | XXXL | null
Jeans | 32x30 | 49.99
Jeans | 32x32 | 49.99
Jeans | 34x32 | 54.99
Jeans | 36x32 | 54.99
Multi-dimensional Arrays
PostgreSQL also supports multi-dimensional arrays:
CREATE TABLE matrix_example (
id SERIAL PRIMARY KEY,
name TEXT,
data INTEGER[][]
);
INSERT INTO matrix_example (name, data)
VALUES ('Example', '{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}');
-- Access specific element (row 2, column 3)
SELECT data[2][3] FROM matrix_example; -- Result: 6
Practical Example: Product Tags
Let's look at a real-world example where arrays are useful - storing product tags:
CREATE TABLE products (
id SERIAL PRIMARY KEY,
name VARCHAR(100),
price NUMERIC(10, 2),
tags TEXT[]
);
INSERT INTO products (name, price, tags)
VALUES
('Smartphone X', 699.99, ARRAY['electronics', 'smartphone', 'new release']),
('Laptop Pro', 1299.99, ARRAY['electronics', 'computer', 'premium']),
('Bluetooth Headphones', 89.99, ARRAY['electronics', 'audio', 'wireless']);
-- Find products with specific tags
SELECT name, price
FROM products
WHERE 'electronics' = ANY(tags) AND 'premium' = ANY(tags);
-- Count products by tag
SELECT unnest(tags) AS tag, COUNT(*)
FROM products
GROUP BY tag
ORDER BY COUNT(*) DESC;
This approach is much cleaner than creating a separate tags table with a many-to-many relationship when your tagging needs are relatively simple.
When to Use (and Not Use) Arrays
Good Use Cases
- Storing a small set of related values (tags, categories, attributes)
- Simple multi-value attributes where joins would be overkill
- Temporary storage of data that will be processed further
When to Avoid
- When you need to frequently update individual elements
- When the array might grow very large (hundreds of elements)
- When you need complex indexing on the individual elements
- When normalization is more appropriate (e.g., when elements have their own attributes)
Summary
PostgreSQL array types provide a powerful way to store multiple values in a single field. They offer flexibility that isn't available in many other relational databases, allowing you to:
- Store multiple values in a single column
- Query and filter based on array contents
- Manipulate arrays with a rich set of operators and functions
While arrays shouldn't replace proper database normalization in many cases, they provide an elegant solution for certain data storage problems, especially when dealing with simple collections of values that logically belong together.
Additional Resources
Exercises
- Create a table to track student exam scores with columns for student name and an array of scores.
- Write a query to find students who have scored above 90 on any exam.
- Calculate the average score for each student using array functions.
- Create a query that returns students and their highest and lowest scores.
- Practice using the
unnest
function to convert an array of dates into individual rows.
If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)