Data Definition Language (DDL)
|
This section documents standard SQL (ISO/IEC 9075-2 (SQL/Foundation)) functionality only. Vendor-specific extensions or behavior of any particular database management system are intentionally left out. In the US, the standard is also distributed via ANSI’s webstore (search "ISO/IEC 9075"). This content was generated with the assistance of AI and should be verified against your target DBMS’s own documentation before relying on it in production. |
Data Definition Language statements create, modify, and remove the structures that hold data: schemas,
tables, views, and indexes. This page covers the standard CREATE, ALTER, and DROP statements, followed
by the constraint clauses that constrain the values a table’s columns may hold. For the authoritative (if less
readable) specification, see ISO/IEC 9075-2 (SQL/Foundation), the part
of the standard that defines these statements and clauses.
CREATE
CREATE SCHEMA
CREATE SCHEMA creates a named namespace that groups related tables, views, and other schema objects
together.
Allowed options:
-
SCHEMA <name>— the schema identifier. Every unqualified object created afterwards within the schema is implicitly qualified by this name. -
AUTHORIZATION <user-name>— optionally names the owner (authorization identifier) of the schema. Either the schema name, theAUTHORIZATIONclause, or both must be present. -
A list of
CREATE TABLE,CREATE VIEW, andGRANTstatements may optionally follow in the same statement, all created within the new schema.
CREATE SCHEMA sales AUTHORIZATION sales_admin;
CREATE TABLE
CREATE TABLE defines a new base table: its name, its columns (each with a data type and optional
column-level constraints), and optional table-level constraints.
Allowed options:
-
<table-name>— the identifier for the new table, optionally schema-qualified (e.g.sales.orders). -
A comma-separated list of column definitions, each consisting of:
-
<column-name>— the column identifier. -
<data-type>— a standard SQL data type. At a conceptual level these fall into a few families:-
Exact numeric:
SMALLINT,INTEGER,BIGINT,NUMERIC(precision, scale),DECIMAL(precision, scale). -
Approximate numeric:
REAL,DOUBLE PRECISION,FLOAT(precision). -
Character:
CHARACTER(length)(fixed-length, blank-padded),CHARACTER VARYING(length)(variable-length),CHARACTER LARGE OBJECT(large text). -
Binary:
BINARY(length),BINARY VARYING(length),BINARY LARGE OBJECT. -
Boolean:
BOOLEAN. -
Date and time:
DATE,TIME,TIMESTAMP(each optionallyWITH TIME ZONE), andINTERVAL.
-
-
Zero or more column constraints (see the Constraints section below):
NOT NULL,UNIQUE,PRIMARY KEY,CHECK (<condition>),REFERENCES <table>[(column)],DEFAULT <value>.
-
-
Zero or more table constraints — constraints not tied to a single column, such as a composite
PRIMARY KEY, a compositeUNIQUE, a table-levelCHECK, or aFOREIGN KEY … REFERENCES …clause. -
ON COMMIT { DELETE ROWS | PRESERVE ROWS }— applicable only to temporary tables (created with aCREATE GLOBAL TEMPORARY TABLEorCREATE LOCAL TEMPORARY TABLEform), controlling whether rows survive past the end of the transaction that inserted them.
CREATE TABLE sales.orders (
order_id INTEGER NOT NULL,
customer_id INTEGER NOT NULL,
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
status CHARACTER VARYING(20) NOT NULL,
total_amount NUMERIC(12, 2) CHECK (total_amount >= 0),
CONSTRAINT pk_orders PRIMARY KEY (order_id),
CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id)
REFERENCES sales.customers (customer_id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
CREATE VIEW
CREATE VIEW defines a virtual table whose contents are derived, at query time, from the result of a
stored SELECT statement.
Allowed options:
-
<view-name>— the identifier for the new view, optionally schema-qualified. -
(<column-name>, …)— an optional explicit list of column names for the view; when omitted, the view’s columns take the names produced by the query. -
AS <query-expression>— theSELECTstatement that defines the view’s contents. This is mandatory. -
WITH [CASCADED | LOCAL] CHECK OPTION— optional. When present, rows inserted or updated through the view must satisfy the view’s ownWHEREcondition.CASCADED(the default) also enforces the check conditions of any view this one is built on;LOCALenforces only this view’s own condition.
CREATE VIEW sales.open_orders AS
SELECT order_id, customer_id, order_date, total_amount
FROM sales.orders
WHERE status = 'OPEN'
WITH CASCADED CHECK OPTION;
CREATE INDEX
Indexes are not part of the ISO/IEC 9075 standard: the standard leaves indexing entirely as an
implementation detail, so there is no standard CREATE INDEX syntax. Every SQL product supports some form of
CREATE INDEX, and the shape shown below is the syntax most implementations converge on in practice, but
treat it as a de-facto convention rather than standard SQL, and check your target DBMS’s own documentation
for the exact syntax and options it supports.
Commonly supported options:
-
UNIQUE— optional keyword requesting that the index also enforce uniqueness of the indexed column values. -
<index-name>— the identifier for the new index. -
ON <table-name> (<column-name> [ASC | DESC], …)— the table and ordered list of columns the index is built over.
CREATE UNIQUE INDEX idx_orders_customer_date
ON sales.orders (customer_id, order_date DESC);
ALTER TABLE
ALTER TABLE changes the structure of an existing table: adding or dropping columns, changing a column’s
definition, or adding and dropping constraints. A single ALTER TABLE statement carries exactly one such
action.
ADD COLUMN
Adds a new column to an existing table.
Allowed options:
-
ADD [COLUMN] <column-name> <data-type> [<column-constraint> …]— the new column’s name, data type, and any column constraints (for exampleDEFAULT,NOT NULL).
ALTER TABLE sales.orders
ADD COLUMN shipped_date DATE;
DROP COLUMN
Removes an existing column from a table.
Allowed options:
-
DROP [COLUMN] <column-name> [CASCADE | RESTRICT]— the column to remove.-
CASCADEalso drops every object that depends on the column (for example a view referencing it). -
RESTRICT(the default in the standard) refuses the operation if any other object depends on the column.
-
ALTER TABLE sales.orders
DROP COLUMN shipped_date RESTRICT;
ALTER/MODIFY COLUMN
Changes the definition of an existing column. The standard expresses this as several distinct, narrower
ALTER COLUMN actions rather than one general-purpose MODIFY COLUMN form.
Allowed options:
-
ALTER [COLUMN] <column-name> SET DEFAULT <value>— sets or replaces the column’s default value. -
ALTER [COLUMN] <column-name> DROP DEFAULT— removes the column’s default value. -
ALTER [COLUMN] <column-name> SET NOT NULL— adds aNOT NULLconstraint to the column. -
ALTER [COLUMN] <column-name> DROP NOT NULL— removes the column’sNOT NULLconstraint. -
ALTER [COLUMN] <column-name> SET DATA TYPE <data-type>— changes the column’s declared data type.
ALTER TABLE sales.orders
ALTER COLUMN total_amount SET DATA TYPE NUMERIC(14, 2);
ALTER TABLE sales.orders
ALTER COLUMN status SET DEFAULT 'OPEN';
ADD / DROP constraint
Adds or removes a table-level constraint after the table has already been created.
Allowed options:
-
ADD CONSTRAINT <constraint-name> <constraint-definition>— adds a new named table constraint (any of the forms described in Constraints below). -
ADD <constraint-definition>— adds an unnamed table constraint; the system generates an implementation defined name for it. -
DROP CONSTRAINT <constraint-name> [CASCADE | RESTRICT]— removes an existing named constraint.-
CASCADEalso drops every object whose definition depends on the constraint. -
RESTRICT(the default in the standard) refuses the operation if any other object depends on the constraint.
-
ALTER TABLE sales.orders
ADD CONSTRAINT chk_orders_status CHECK (status IN ('OPEN', 'SHIPPED', 'CANCELLED'));
ALTER TABLE sales.orders
DROP CONSTRAINT chk_orders_status RESTRICT;
DROP
Removes an existing schema object. The standard DROP forms share the same overall shape: the object kind,
its name, and a CASCADE/RESTRICT clause governing what happens to dependent objects.
-
CASCADE— also drops every object that depends on the one being dropped (for example, views built on a dropped table, or indexes and constraints on a dropped table). -
RESTRICT— refuses the operation if any other object depends on the one being dropped. This is the default behavior in the standard when neither keyword is specified.
DROP INDEX
As noted under CREATE INDEX, indexes are outside the scope of the ISO/IEC 9075 standard, so there is no
standard DROP INDEX syntax either. The form below reflects the common convention; consult your target
DBMS’s documentation for its exact syntax.
DROP INDEX idx_orders_customer_date;
Constraints
Constraints restrict the values a column or a row may hold. They can be declared inline as column
constraints (immediately after a single column’s data type) or separately as table constraints (referring
to one or more columns by name), and either form may optionally be named with CONSTRAINT <constraint-name>
so it can later be dropped or altered by name.
PRIMARY KEY
Declares one column, or a comma-separated set of columns, whose combined values uniquely identify each row
in the table. A table may have at most one primary key. Every column that participates in a primary key is
implicitly NOT NULL, and the combination of values across the primary key columns must be unique.
CREATE TABLE sales.order_items (
order_id INTEGER NOT NULL,
line_number INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
CONSTRAINT pk_order_items PRIMARY KEY (order_id, line_number)
);
FOREIGN KEY
Declares that the value(s) of one column, or set of columns, must match a value that exists in the
referenced table’s primary key or a UNIQUE constraint of that table (or be entirely NULL, unless
NOT NULL is also specified).
Allowed clauses:
-
FOREIGN KEY (<column>, …) REFERENCES <table-name> [(<column>, …)]— the referencing column(s) and the referenced table. When the referenced column list is omitted, the referenced table’s primary key is used. -
ON DELETE <referential-action>— the action taken when a referenced row is deleted. -
ON UPDATE <referential-action>— the action taken when a referenced row’s key value is updated. -
<referential-action>is one of:-
CASCADE— propagate the delete/update to the referencing rows. -
SET NULL— set the referencing column(s) toNULL. -
SET DEFAULT— set the referencing column(s) to their default value. -
RESTRICT— refuse the delete/update immediately if any referencing row exists. -
NO ACTION(the default when neither clause is specified) — refuse the delete/update if any referencing row still exists once all other referential actions of the same statement have been applied.
-
CREATE TABLE sales.order_items (
order_id INTEGER NOT NULL,
line_number INTEGER NOT NULL,
product_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
CONSTRAINT pk_order_items PRIMARY KEY (order_id, line_number),
CONSTRAINT fk_order_items_order FOREIGN KEY (order_id)
REFERENCES sales.orders (order_id)
ON DELETE CASCADE
ON UPDATE NO ACTION
);
UNIQUE
Declares that the combination of values in one column, or a comma-separated set of columns, must be unique
across every row of the table. Unlike PRIMARY KEY, a table may declare any number of UNIQUE constraints,
and the participating columns are not automatically made NOT NULL; standard SQL permits multiple rows with
NULL in a UNIQUE column, since two NULL values are never considered equal to one another.
CREATE TABLE sales.customers (
customer_id INTEGER NOT NULL,
email CHARACTER VARYING(255),
CONSTRAINT pk_customers PRIMARY KEY (customer_id),
CONSTRAINT uq_customers_email UNIQUE (email)
);
NOT NULL
A column constraint that forbids the column from holding a NULL value in any row. It can only be declared
as a column constraint, not as a separate table constraint.
CREATE TABLE sales.customers (
customer_id INTEGER NOT NULL,
full_name CHARACTER VARYING(120) NOT NULL
);
CHECK
Declares a boolean <condition> that every row of the table must satisfy (the row is rejected if the
condition evaluates to FALSE; a condition that evaluates to UNKNOWN, for example because it involves a
NULL, does not violate the constraint). It may reference a single column, as a column constraint, or
multiple columns, as a table constraint.
CREATE TABLE sales.orders (
order_id INTEGER NOT NULL,
order_date DATE NOT NULL,
ship_date DATE,
total_amount NUMERIC(12, 2),
CONSTRAINT pk_orders PRIMARY KEY (order_id),
CONSTRAINT chk_orders_amount CHECK (total_amount >= 0),
CONSTRAINT chk_orders_dates CHECK (ship_date IS NULL OR ship_date >= order_date)
);
DEFAULT
A column constraint that supplies the value a column takes when an INSERT statement does not explicitly
provide one. The default value may be a literal, a niladic datetime function such as CURRENT_DATE,
CURRENT_TIME, or CURRENT_TIMESTAMP, NULL, or the implementation-defined system default.
CREATE TABLE sales.orders (
order_id INTEGER NOT NULL,
order_date DATE NOT NULL DEFAULT CURRENT_DATE,
status CHARACTER VARYING(20) NOT NULL DEFAULT 'OPEN',
CONSTRAINT pk_orders PRIMARY KEY (order_id)
);