CREATE TABLE
CREATE TABLE defines a new table.
Supported syntax
CREATE TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option ... ] } [, ... ] ] ) where column_constraint is: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY ( sequence_options ) | UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) | UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters | PRIMARY KEY ( column_name [, ... ] ) index_parameters | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH FULL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] and referential_action in a FOREIGN KEY/REFERENCES constraint is: { NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] } and like_option is: { INCLUDING | EXCLUDING } { COMMENTS | CONSTRAINTS | DEFAULTS | GENERATED | IDENTITY | INDEXES | STATISTICS | ALL } index_parameters in UNIQUE and PRIMARY KEY constraints are: [ INCLUDE ( column_name [, ... ] ) ]
Identity columns
Note
When using identity columns, the cache value should be carefully considered. For more information, see the Important callout on the CREATE SEQUENCE page.
For guidance on how best to use identity columns based on workload patterns, see Working with sequences and identity columns.
The GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY (
clause creates the column as an identity column. It will have an implicit
sequence attached to it and in newly-inserted rows the column will automatically have values
from the sequence assigned to it. Such a column is implicitly sequence_options )NOT NULL.
The clauses ALWAYS and BY DEFAULT determine how explicitly
user-specified values are handled in INSERT and UPDATE
commands.
In an INSERT command, if ALWAYS is selected, a user-specified
value is only accepted if the INSERT statement specifies OVERRIDING SYSTEM
VALUE. If BY DEFAULT is selected, then the user-specified value takes
precedence.
In an UPDATE command, if ALWAYS is selected, any update of the
column to any value other than DEFAULT will be rejected. If BY
DEFAULT is selected, the column can be updated normally. (There is no
OVERRIDING clause for the UPDATE command.)
The sequence_options clause can be used to override the
parameters of the sequence. The available options include those shown for
CREATE SEQUENCE, plus SEQUENCE NAME
. Without nameSEQUENCE NAME, the system chooses
an unused name for the sequence.
Storage mode
The optional STORAGE clause sets the storage mode for the column. Use
these options to control the behavior of compression for variable-length data types such as
JSON, JSONB, TEXT, VARCHAR, and BPCHAR.
Amazon Aurora DSQL compresses some data types when they exceed a certain size. To disable
this behavior, use the PLAIN or EXTERNAL options.
PLAIN-
Aurora DSQL stores data inline without compression. This is the only option for fixed-length data types such as
integer. Use this option to disable compression on some variable-length types. MAIN|EXTENDED|DEFAULT-
MAINandEXTENDEDallow optional compression of the column if the underlying data type supports compression.DEFAULTsets the storage mode to the default mode for the column's data type. EXTERNAL-
Aurora DSQL doesn't currently support TOAST tables, however
EXTERNALdisables compression on data types that support compression.
Foreign key constraints
The REFERENCES and FOREIGN KEY clauses specify a foreign key
constraint, which requires that a group of one or more columns of the new table must only
contain values that match values in the referenced column(s) of some row of the referenced
table. If you omit the refcolumn list, Aurora DSQL uses the primary
key of the reftable. Otherwise, the
refcolumn list must refer to the columns of a non-deferrable
unique or primary key constraint.
Aurora DSQL matches a value inserted into the referencing column(s) against the values of the
referenced table and referenced columns using the given match type. There are two supported
match types: MATCH FULL and MATCH SIMPLE (which is the
default).
You can define a foreign key as either a column constraint or a table constraint:
-
Column constraint (REFERENCES) – Use
REFERENCESafter the column data type for single-column foreign keys. -
Table constraint (FOREIGN KEY) – Use
FOREIGN KEY (...) REFERENCES ...for single-column or multi-column foreign keys.
Referential actions
When you change data in the referenced columns, Aurora DSQL performs actions on the data
in the referencing table's columns. The ON DELETE clause specifies the action
to perform when a transaction deletes a referenced row in the referenced table. Likewise,
the ON UPDATE clause specifies the action to perform when a transaction
updates a referenced column to a new value. If a transaction updates the row but doesn't change the referenced
column, Aurora DSQL takes no action.
Aurora DSQL supports the following referential actions:
NO ACTION(default)-
Produces an error if the deletion or update would create a foreign key constraint violation. If the constraint is deferred, Aurora DSQL produces this error at constraint check time if any referencing rows still exist. This is the default action.
RESTRICT-
Produces an error if a row to be deleted or updated matches a row in the referencing table. This prevents the action even if the state after the action wouldn't violate the foreign key constraint. In particular, it prevents updates of referenced rows to values that are distinct but compare as equal. Unlike
NO ACTION, theRESTRICTcheck can't be deferred.
Cascading actions count towards transaction modification limits
The CASCADE, SET NULL, and SET DEFAULT actions
automatically modify rows in the referencing table when a referenced row is updated or
deleted. The Aurora DSQL transaction row limit applies to these actions and can cause unexpected failures
if not used carefully. Prefer NO ACTION or RESTRICT for foreign key
relationships where child-row cardinality is unbounded or unpredictable. For more information, see Database limits in Aurora DSQL.
CASCADE-
Delete any rows referencing the deleted row, or update the values of the referencing column(s) to the new values of the referenced columns, respectively.
SET NULL [ ( column_name [, ... ] ) ]-
Set all of the referencing columns, or a specified subset of the referencing columns, to null. A subset of columns can only be specified for
ON DELETEactions. SET DEFAULT [ ( column_name [, ... ] ) ]-
Set all of the referencing columns, or a specified subset of the referencing columns, to their default values. A subset of columns can only be specified for
ON DELETEactions. (There must be a row in the referenced table matching the default values, if they are not null, or the operation will fail.)
Match types
Aurora DSQL supports the following match types:
MATCH SIMPLE(default)-
Allows any of the foreign key columns to be null. If any of them are null, the row isn't required to have a match in the referenced table.
MATCH FULL-
Doesn't allow one column of a multi-column foreign key to be null unless all foreign key columns are null. If they are all null, the row isn't required to have a match in the referenced table.
You can apply NOT NULL constraints to the referencing columns to prevent
these cases from arising.
Deferrability
You can control when a foreign key constraint is checked by specifying its deferrability:
NOT DEFERRABLE(default)-
Aurora DSQL checks this constraint immediately after each statement. You can't change it to deferred with
SET CONSTRAINTS. DEFERRABLE-
The constraint can be deferred to the end of the transaction using
SET CONSTRAINTS. Without anINITIALLYclause, this defaults toINITIALLY IMMEDIATE. DEFERRABLE INITIALLY IMMEDIATE-
By default, Aurora DSQL checks this constraint after each statement, but you can defer it within a transaction by using
SET CONSTRAINTS ... DEFERRED. DEFERRABLE INITIALLY DEFERRED-
By default, Aurora DSQL checks this constraint at transaction commit time. You can change it to immediate within a transaction by using
SET CONSTRAINTS ... IMMEDIATE.
For more information about changing constraint check timing within a transaction, see SET CONSTRAINTS.
Foreign key constraints only
In Aurora DSQL, the DEFERRABLE option applies to foreign key constraints
only.
Foreign key constraint examples
Assume you have a table storing products:
CREATE TABLE products ( product_no integer PRIMARY KEY, name text, price numeric );
Now you want a table storing orders of those products. You want to ensure that the orders table contains references to products that actually exist. Define a foreign key constraint in the orders table that references the products table:
CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer REFERENCES products (product_no), quantity integer );
Now you can't create orders with non-NULL product_no entries
that don't appear in the products table.
In this situation, the orders table is the referencing table and the products table is the referenced table. Similarly, there are referencing and referenced columns.
You can shorten the above command to:
CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer REFERENCES products, quantity integer );
If you omit the column list, Aurora DSQL uses the primary key of the referenced table as the referenced column(s).
You can assign your own name for a foreign key constraint in the usual way:
CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer CONSTRAINT fk_product REFERENCES products, quantity integer );
A foreign key can also constrain and reference a group of columns. It then needs to be written in table constraint form:
CREATE TABLE inventory ( warehouse_id integer, product_no integer, quantity integer, PRIMARY KEY (warehouse_id, product_no) ); CREATE TABLE shipments ( shipment_id integer PRIMARY KEY, warehouse_id integer, product_no integer, FOREIGN KEY (warehouse_id, product_no) REFERENCES inventory (warehouse_id, product_no) );
The number and types of the constrained columns need to be compatible with the number and types of the referenced columns.
A table can have more than one foreign key constraint. This is used to implement many-to-many relationships between tables:
CREATE TABLE order_items ( product_no integer REFERENCES products, order_id integer REFERENCES orders, quantity integer, PRIMARY KEY (product_no, order_id) );
A foreign key constraint can reference the same table it belongs to. This is called a self-referential foreign key. For example, if you want rows of a table to represent nodes of a tree structure, you could write:
CREATE TABLE tree ( node_id integer PRIMARY KEY, parent_id integer REFERENCES tree, name text );
A top-level node would have NULL parent_id, while non-NULL
parent_id entries are constrained to reference valid rows of the
table.
You can specify referential actions to control what happens when a referenced row is
deleted or updated. The following example uses ON DELETE RESTRICT to prevent
deletion of a product that is still referenced by an order:
CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer REFERENCES products ON DELETE RESTRICT, quantity integer );
With RESTRICT, attempting to delete a product that has orders referencing
it produces an error immediately. With the default NO ACTION, the check
can be deferred to the end of the transaction if the constraint is declared
DEFERRABLE.
To create a foreign key that can be deferred to the end of a transaction, use the
DEFERRABLE option. This is useful when you need to insert rows in both
tables within the same transaction regardless of order:
CREATE TABLE orders ( order_id integer PRIMARY KEY, product_no integer REFERENCES products DEFERRABLE INITIALLY DEFERRED, quantity integer );
With DEFERRABLE INITIALLY DEFERRED, the constraint isn't checked until
commit time. You can insert the order row before the product row exists, as long as the
product row is present when the transaction commits.
To use MATCH FULL with a composite foreign key, which requires that all
referencing columns are null together or all non-null together:
CREATE TABLE shipments ( shipment_id integer PRIMARY KEY, warehouse_id integer, product_no integer, FOREIGN KEY (warehouse_id, product_no) REFERENCES inventory (warehouse_id, product_no) MATCH FULL );