This section is from the "Practical PostgreSQL" book, by John Worsley and Joshua Drake. Also available from Amazon: Practical PostgreSQL.
If you perform a slash h (\h) on create table, you may have noticed that there are additional notes on how to create a table or column constraint. The portion that applies to a column constraint is as follows:
where column_constraint can be: [CONSTRAINT constraint_name] { NOT NULL | NULL | UNIQUE | PRIMARY KEY | DEFAULT value | CHECK ( condition ) | REFERENCES table [ ( column ) ] [ MATCH FULL | MATCH PARTIAL ] [ ON DELETE action ] [ ON UPDATE action ] [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] }
There are five column constraints available:
Not Null
Unique
Primary Key
Check
References
The definitions for each clause are:
NULL specifies that this column is allowed to have NULL values. This is the default so you don't need to implicitly specify this. This is only allowed as a column constraint, not a table constraint.
NOT NULL specifies that this column is not allowed to contain NULL values. Using the constraint CHECK ( column NOT NULL) is the equivalent to using NOT NULL.
This column can contain only unique non-repeating values. UNIQUE does not necessarily mean NOT NULL. UNIQUE allows repeating NULL values to be in a column.
This column may contain only unique and non-null values. A table or column primary key is restricted to having only one primary key.
This constraint defines tests that the column must satisfy for an insert or update operation to succeed on that row. The condition is an expression that must return a boolean result. For column constraint definitions, only one column can be referenced by the CHECK clause.
The following clauses apply to reference constraints:
The values in this column are checked against the values of another column that this references.
reftable - this table contains the data that are compared with.
refcolumn - this column is located in the reftable to compare data against. If refcolumn is left empty, then the PRIMARY KEY of the reftable is used.
MATCH FULL rules out foreign key columns that contain NULL values, unless all foreign key columns are NULL. MATCH PARTIAL is not supported, but a default type is. The default allows NULL columns to satisfy the constraint.
When a DELETE is performed on a referenced row in the referenced table, one of these possible actions should likewise be executed:
NO ACTION - Produces an error if the foreign key is violated. This is the default if an action is not specified.
RESTRICT - Same as NO ACTION.
CASCADE - Removes all rows which references the deleted row.
SET NULL - Assigns a NULL to all referenced column values.
SET DEFAULT - Sets all referenced columns to their default values.
When an UPDATE is performed on a referenced row in the referenced table, an action occurs. If a row is updated, but the referenced column is not affected, then the action will not occur. The possible actions that can occur when an UPDATE is applied to a referenced column are the same as with ON DELETE. The only exception is the CASCADE action. CASCADE updates all of the rows which references the updated row.
DEFERRABLE specifies the constraint to be postponed to the end of the transaction.
NOT DEFERRABLE means that the constraint is not postponed to the end of the transaction. This is the default when DEFERRABLE is not specified.
The constraint must be DEFERRABLE for you to specify a check time. The possible check times for a constraint to be deferred are:
DEFERRED - postpone constraint checking until the end of the transaction is reached.
IMMEDIATE - perform constraint checking after each statement. This is the default when a checktime is not specified.
To create a primary key column constraint on an employees table, use:
Example 5-21. Creating a Primary Key Constraint
CREATE TABLE employees ( emp_id INTEGER PRIMARY KEY, name TEXT );
This is the equivalent to the above operation:
CREATE TABLE employees ( emp_id INTEGER, name TEXT, PRIMARY KEY (emp_id) );
This creates a new table with a check column constraint that applies a rule which makes sure that employee identification numbers are greater than 100 and are non-NULL values. It also makes sure that an employee name exists for each employee id:
CREATE TABLE employees ( emp_id INTEGER NOT NULL CHECK (emp_id > 100), name TEXT NOT NULL CHECK (name <> '') );
![]() | Note |
---|---|
When using the Check option to restrict the columns from containing empty values, there are different ways to express this depending on the data type of the column. You can specify a 0 for integer data type, or a pair of empty single quotes for text. If you use a pair of empty quotes for integer type, then it will automatically convert that into a 0. Keep in mind that when you perform a check condition, the condition must return the same data type as the column value that you are checking. |
If you have an existing table that you want to apply a constraint on, then you can use the alter table command. The command below performs the exact same check condition as the above command for employee identification numbers:
Example 5-22. Using a Constraint on an Existing Table
ALTER TABLE employees ADD CONSTRAINT emp_id_check CHECK (emp_id > 100);
The employee table currently contains these data values for the employee identification numbers:
SELECT emp_id FROM employees; emp_id -------- 100 101 102 103 (4 rows)
After having executed the ALTER TABLE command, this message may have appeared:
ERROR: AlterTableAddConstraint: rejected due to CHECK constraint emp_id_check
This problem arises when the constraint you are creating conflicts with the data that is currently stored in the table. We can correct this problem by changing the constraint to check for employee identification numbers greater than and equal to 100:
ALTER TABLE employees ADD CONSTRAINT emp_id_check CHECK (emp_id >= 100);
![]() | Creating a Constraint with ALTER TABLE |
---|---|
To create a constraint using the ALTER TABLE command requires the following:
If the above rules are not met, the constraint is not created. Using the CREATE TABLE command does not require these rules because the table and column is in the stage of creation and the constraint can be any valid constraint because there are no data values stored in the table yet. |
 
Continue to: