Summary: in this tutorial, you’ll learn how to use PostgreSQL CHECK constraint to ensure values in table columns meet a condition.
Introduction to PostgreSQL CHECK constraint #
PostgreSQL CHECK constraints maintain data integrity by ensuring that the value in a column must satisfy a Boolean expression.
When a column has a constraint, and you attempt to insert or update a value that causes the Boolean expression to be false, PostgreSQL issues a constraint violation and rejects the changes.CHECK
CHECK constraints can be helpful to enforce data integrity rules at the database level. They prevent invalid data from being inserted or update in table columns.
For example, you can use the CHECK constraint to prevent negative values from being inserted into the price column of the products table.
Here’s the syntax of the constraint:CHECK
CREATE TABLE table_name (
column1 data_type CONSTRAINT constraint_name CHECK(boolean_expression),
...
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)In this syntax:
- First, add a
CHECKconstraint to the table column. - Second, provide a constraint name after the
CONSTRAINTkeyword. This constraint name will show up in the error if a constraint violation error occurs. If you don’t provide the constraint name, PostgreSQL will implicitly generate one for the constraint. - Third, place a Boolean expression inside parentheses
()after theCHECKkeyword to check values being inserted or updated in the column. The Boolean expression can reference columns of the same table, not other tables.
Here’s the more concise syntax that does not use the constraint name:
CREATE TABLE table_name (
column1 data_type CHECK(boolean_expression),
...
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)This CHECK constraint is a column constraint because it attaches to a particular column (column1).
It’s worth noting that you can apply multiple constraints to the same column. For example, you can use both NOT NULL and CHECK constraints for the same column:
CREATE TABLE table_name (
column1 data_type NOT NULL CHECK(boolean_expression),
...
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Alternatively, you can define the CHECK constraint as a table constraint:
CREATE TABLE table_name (
column1 data_type NOT NULL,
...,
CHECK(boolean_expression)
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)In this syntax, you define the CHECK constraint after the column list. This syntax is handy when referencing multiple table columns in the Boolean expression.
Basic PostgreSQL CHECK constraint example #
First, create a table called products with a CHECK constraint to ensure that the price is greater than or equal to 0:
CREATE TABLE products (
product_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DEC(11, 2) NOT NULL CONSTRAINT positive_price CHECK (price >= 0),
discounted_price DEC(11, 2) NOT NULL DEFAULT 0
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Next, attempt to insert a row with a negative price into the products table:
INSERT INTO
products (name, price)
VALUES
('iPhone Pro 15', -1299.99);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)PostgreSQL issued the following error:
new row for relation "products" violates check constraint "positive_price"Code language: plaintext (plaintext)Then, insert a new row with a valid price:
INSERT INTO
products (name, price)
VALUES
('iPhone Pro 15', 1299.99) RETURNING *;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
product_id | name | price | discounted_price
------------+---------------+---------+------------------
2 | iPhone Pro 15 | 1299.99 | 0.00After that, update the price to an invalid one:
UPDATE products
SET
price = -899.99
WHERE
product_id = 2;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)PostgreSQL issued the same check constraint violation:
new row for relation "products" violates check constraint "positive_price"Code language: plaintext (plaintext)Finally, update the price to a valid one:
UPDATE products
SET
price = 999.99
WHERE
product_id = 2
RETURNING *;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
product_id | name | price | discounted_price
------------+---------------+--------+------------------
2 | iPhone Pro 15 | 999.99 | 0.00The output indicates that the statement updated the product price successfully.
Adding CHECK constraints to tables #
You use ALTER TABLE ... ADD CONSTRAINT statement to add a CHECK constraint to an existing table.
Here’s the syntax of the statement:
ALTER TABLE table_name
ADD CONSTRAINT constraint_name
CHECK (boolean_expression)Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)For example, the following statement adds a CHECK constraint to check if the discounted price is less than price:
ALTER TABLE products
ADD CONSTRAINT discounted_price_check
CHECK (discounted_price < price AND discounted_price > 0);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)PostgreSQL issues an error because some row in the table violates the new CHECK constraint:
check constraint "discounted_price_check" of relation "products" is violated by some rowCode language: plaintext (plaintext)The reason is that row id 2 has a discounted price of 0, which violates the new CHECK constraint.
To fix this, you can update the discounted price of the existing rows to make it valid for the new CHECK constraint:
UPDATE products
SET discounted_price = price * 0.9
RETURNING *;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
product_id | name | price | discounted_price
------------+---------------+--------+------------------
2 | iPhone Pro 15 | 999.99 | 899.99And then add the CHECK constraint to the products table again:
ALTER TABLE products
ADD CONSTRAINT discounted_price_check
CHECK (discounted_price < price AND discounted_price > 0);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)If you attempt to insert a row with the discounted price higher or equal to the price, PostgreSQL will issue a check violation. For example:
INSERT INTO products(name, price, discounted_price)
VALUES('iPhone Pro 15', 1299.99, 1399.99);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Error:
ERROR: new row for relation "products" violates check constraint "discounted_price_check"Code language: plaintext (plaintext)Removing CHECK constraints from tables #
To remove a CHECK constraint from a table, you use the ALTER TABLE ... DROP CONSTRAINT statement:
ALTER TABLE table_name
DROP CONSTRAINT IF EXISTS constraint_name;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)In this syntax:
- First, specify the table name from which you want to remove the
CHECKconstraint. - Second, provide the constraint name in the
DROP CONSTRAINTclause to remove it. - Third, use the optional
IF EXISTSoption to prevent an error from attempting to remove a non-existingCHECKconstraint.
For example, the following statement drops the discounted_priceCHECK constraint from the products table:
ALTER TABLE products
DROP CONSTRAINT IF EXISTS discounted_price_check;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Summary #
- A
CHECKconstraint adds a validation logic to one or more columns in a table to ensure data integrity. - Use the
CONSTRAINT ... CHECKto define aconstraint for a table.CHECK - Use the
ALTER TABLE ... ADD CONSTRAINTstatement to add aCHECKconstraint to a table. - Use the
ALTER TABLE ... DROP CONSTRAINTstatement to remove aCHECKconstraint from a table.