PostgreSQL Operators
Operators are essential symbols or keywords that perform operations on one or more expressions in PostgreSQL. Understanding operators is fundamental to writing effective queries and manipulating data efficiently.
Introduction
In PostgreSQL, operators allow you to perform various operations on data, from simple arithmetic calculations to complex pattern matching. They form the building blocks of expressions used in your SQL queries and help transform, filter, and manipulate data to get the results you need.
This guide will walk you through the main categories of PostgreSQL operators and provide practical examples of how to use them effectively.
Arithmetic Operators
Arithmetic operators perform mathematical calculations on numeric data types.
Operator | Description | Example | Result |
---|---|---|---|
+ | Addition | SELECT 5 + 3; | 8 |
- | Subtraction | SELECT 5 - 3; | 2 |
* | Multiplication | SELECT 5 * 3; | 15 |
/ | Division | SELECT 5 / 2; | 2.5 |
% | Modulo (remainder) | SELECT 5 % 2; | 1 |
^ | Exponentiation | SELECT 2 ^ 3; | 8 |
` | /` | Square root | `SELECT |
` | /` | Cube root | |
! | Factorial | SELECT 5!; | 120 |
Practical Example
Let's say we have a table called products
with columns for price
and quantity
. We can use arithmetic operators to calculate the total value:
-- Calculate total value of each product
SELECT
product_name,
price,
quantity,
price * quantity AS total_value
FROM
products;
Result:
product_name | price | quantity | total_value
--------------+-------+----------+-------------
Keyboard | 29.99 | 10 | 299.90
Mouse | 15.50 | 20 | 310.00
Monitor | 149.99| 5 | 749.95
Comparison Operators
Comparison operators compare values and return boolean results (true/false).
Operator | Description | Example | Result |
---|---|---|---|
= | Equal | SELECT 5 = 5; | t |
<> or != | Not equal | SELECT 5 <> 3; | t |
< | Less than | SELECT 3 < 5; | t |
> | Greater than | SELECT 5 > 3; | t |
<= | Less than or equal | SELECT 3 <= 3; | t |
>= | Greater than or equal | SELECT 3 >= 3; | t |
Using Comparison Operators in WHERE Clauses
-- Find all expensive products (price > 100)
SELECT
product_name,
price
FROM
products
WHERE
price > 100;
Result:
product_name | price
--------------+--------
Monitor | 149.99
Laptop | 899.99
Printer | 199.50
Logical Operators
Logical operators combine boolean values.
Operator | Description | Example | Result |
---|---|---|---|
AND | Logical AND | SELECT (true AND false); | f |
OR | Logical OR | SELECT (true OR false); | t |
NOT | Logical NOT | SELECT NOT false; | t |
Complex Filtering with Logical Operators
-- Find products with price between $50 and $200
SELECT
product_name,
price
FROM
products
WHERE
price >= 50
AND price <= 200;
Result:
product_name | price
--------------+--------
Monitor | 149.99
Printer | 199.50
Headphones | 89.99
String Operators
PostgreSQL offers several operators for working with text data.
Operator | Description | Example | Result |
---|---|---|---|
|| | String concatenation | SELECT 'Hello' || ' ' || 'World'; | Hello World |
LIKE | Pattern matching with wildcards | SELECT 'apple' LIKE 'app%'; | t |
ILIKE | Case-insensitive LIKE | SELECT 'Apple' ILIKE 'app%'; | t |
~ | Matches regex, case-sensitive | SELECT 'apple' ~ '^a'; | t |
~* | Matches regex, case-insensitive | SELECT 'Apple' ~* '^a'; | t |
!~ | Does not match regex, case-sensitive | SELECT 'apple' !~ '^b'; | t |
!~* | Does not match regex, case-insensitive | SELECT 'Apple' !~* '^b'; | t |
Finding Products by Name Pattern
-- Find all products containing "phone" in their name
SELECT
product_name,
price
FROM
products
WHERE
product_name ILIKE '%phone%';
Result:
product_name | price
--------------+-------
Smartphone | 499.99
Headphones | 89.99
Microphone | 59.99
JSON Operators
PostgreSQL has powerful JSON operators for working with JSON data.
Operator | Description | Example | Result |
---|---|---|---|
-> | Get JSON array element or object field as JSON | SELECT '{"name":"John"}'::json->'name'; | "John" |
->> | Get JSON array element or object field as text | SELECT '{"name":"John"}'::json->>'name'; | John |
#> | Get JSON object at the specified path | SELECT '{"user":{"name":"John"}}'::json#>'{user,name}'; | "John" |
#>> | Get JSON object at the specified path as text | SELECT '{"user":{"name":"John"}}'::json#>>'{user,name}'; | John |
Working with JSON Data
-- Assuming we have a table with JSON data
CREATE TABLE user_profiles (
id SERIAL PRIMARY KEY,
data JSONB
);
INSERT INTO user_profiles (data) VALUES
('{"name": "Alice", "contact": {"email": "[email protected]", "phone": "123-456-7890"}}'),
('{"name": "Bob", "contact": {"email": "[email protected]", "phone": "098-765-4321"}}');
-- Query to extract email addresses
SELECT
data->>'name' AS name,
data#>>'{contact,email}' AS email
FROM
user_profiles;
Result:
name | email
--------+--------------------
Alice | [email protected]
Bob | [email protected]
Array Operators
PostgreSQL supports operations on array types.
Operator | Description | Example | Result |
---|---|---|---|
= | Equal | SELECT ARRAY[1,2,3] = ARRAY[1,2,3]; | t |
@> | Contains | SELECT ARRAY[1,2,3] @> ARRAY[2,3]; | t |
<@ | Is contained by | SELECT ARRAY[2,3] <@ ARRAY[1,2,3,4]; | t |
&& | Overlaps (have elements in common) | SELECT ARRAY[1,2] && ARRAY[2,3]; | t |
` | ` | Array concatenation |
Working with Arrays
-- Create a table with array data
CREATE TABLE tags (
id SERIAL PRIMARY KEY,
item_name TEXT,
categories TEXT[]
);
INSERT INTO tags (item_name, categories) VALUES
('Laptop', ARRAY['Electronics', 'Computers', 'Office']),
('Coffee Mug', ARRAY['Kitchen', 'Office', 'Gifts']);
-- Find items in the 'Office' category
SELECT
item_name,
categories
FROM
tags
WHERE
categories @> ARRAY['Office'];
Result:
item_name | categories
-------------+--------------------------------------
Laptop | {Electronics,Computers,Office}
Coffee Mug | {Kitchen,Office,Gifts}
Date/Time Operators
PostgreSQL has operators for working with date and time data.
Operator | Description | Example | Result |
---|---|---|---|
+ | Addition | SELECT DATE '2023-01-01' + INTEGER '7'; | 2023-01-08 |
- | Subtraction | SELECT DATE '2023-01-10' - INTEGER '5'; | 2023-01-05 |
- | Difference | SELECT DATE '2023-01-10' - DATE '2023-01-01'; | 9 |
@ | Absolute value (for intervals) | SELECT @ INTERVAL '-5 days'; | 5 days |
Date Calculations
-- Assuming we have an orders table
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
order_date DATE,
delivery_date DATE
);
INSERT INTO orders (order_date, delivery_date) VALUES
('2023-01-01', '2023-01-05'),
('2023-01-10', '2023-01-18'),
('2023-01-15', '2023-01-25');
-- Calculate delivery duration
SELECT
id,
order_date,
delivery_date,
delivery_date - order_date AS delivery_days
FROM
orders;
Result:
id | order_date | delivery_date | delivery_days
----+------------+---------------+--------------
1 | 2023-01-01 | 2023-01-05 | 4
2 | 2023-01-10 | 2023-01-18 | 8
3 | 2023-01-15 | 2023-01-25 | 10
Network Address Operators
PostgreSQL includes operators for IP address manipulation.
Operator | Description | Example | Result |
---|---|---|---|
<< | Is contained within | SELECT inet '192.168.1.5' << inet '192.168.1.0/24'; | t |
>> | Contains | SELECT inet '192.168.1.0/24' >> inet '192.168.1.5'; | t |
&& | Overlaps | SELECT inet '192.168.1.0/24' && inet '192.168.1.128/25'; | t |
~ | Bitwise NOT | SELECT ~ inet '192.168.1.5'; | 63.87.254.250 |
IP Address Filtering
-- Create a table for access logs
CREATE TABLE access_logs (
id SERIAL PRIMARY KEY,
ip_address INET,
access_time TIMESTAMP,
resource TEXT
);
INSERT INTO access_logs (ip_address, access_time, resource) VALUES
('192.168.1.5', '2023-01-01 10:00:00', '/home'),
('192.168.2.10', '2023-01-01 10:05:00', '/products'),
('10.0.0.15', '2023-01-01 10:10:00', '/cart');
-- Find all accesses from a specific subnet
SELECT
id,
ip_address,
resource
FROM
access_logs
WHERE
ip_address << inet '192.168.0.0/16';
Result:
id | ip_address | resource
----+-------------+------------
1 | 192.168.1.5 | /home
2 | 192.168.2.10| /products