Project: YugabyteDB (App Definition and Development / Database)
File: ddl_create_table.md

title: CREATE TABLE [YSQL] headerTitle: CREATE TABLE linkTitle: CREATE TABLE description: Use the CREATE TABLE statement to create a table in a database. menu: v2.18: identifier: ddlcreatetable parent: statements type: docs Use the `CREATE TABLE` statement to create a table in a database. It defines the table name, column names and types, primary key, and table properties. {{%ebnf%}} create_table, table_elem, column_constraint, table_constraint, key_columns, hash_columns, range_columns, storage_parameters, storage_parameter, index_parameters, references_clause, split_row {{%/ebnf%}} Create a table with table_name. If `qualified_name` already exists in the specified database, an error will be raised unless the `IF NOT EXISTS` clause is used. Primary key can be defined in either `columnconstraint` or `tableconstraint`, but not in both. There are two types of primary key columns: `Hash primary key columns`: The primary key may have zero or more leading hash-partitioned columns. By default, only the first column is treated as the hash-partition column. But this behavior can be modified by explicit use of the HASH annotation. `Range primary key columns`: A table can have zero or more range primary key columns and it controls the top-level ordering of rows within a table (if there are no hash partition columns) or the ordering of rows among rows that share a common set of hash partitioned column values. By default, the range primary key columns are stored in ascending order. But this behavior can be controlled by explicit use of `ASC` or `DESC`. For example, if the primary key specification is `PRIMARY KEY ((a, b) HASH, c DESC)`, then columns `a` & `b` are used together to hash partition the table, and rows that share the same values for `a` and `b` are stored in descending order of their value for `c`. If the primary key specification is `PRIMARY KEY(a, b)`, then column `a` is used to hash partition the table, and rows that share the same value for `a` are stored in ascending order of their value for `b`. `FOREIGN KEY` and `REFERENCES` specifies that the set of columns can only contain values that are present in the referenced column(s) of the referenced table. It is used to enforce referential integrity of data. This enforces that the set of columns specified in the `UNIQUE` constraint are unique in the table, that is, no two rows can have the same values for the set of columns specified in the `UNIQUE` constraint. This is used to enforce that data in the specified table meets the requirements specified in the `CHECK` clause. This clause is used to specify a default value for the column. If an `INSERT` statement does not specify a value for the column, then the default value is used. If no default is specified for a column, then the default is NULL. Constraints can be deferred using the `DEFERRABLE`

Currently, only foreign key constraints can be deferred in YugabyteDB. A constraint that is not deferrable will be checked after every row in a statement. In the case of deferrable constraints, the checking of the constraint can be postponed until the end of the transaction. Constraints marked as `INITIALLY IMMEDIATE` will be checked after every row in a statement. Constraints marked as `INITIALLY DEFERRED` will be checked at the end of the transaction. Using this qualifier will create a temporary table. Temporary tables are visible only in the current client session or transaction in which they are created and are automatically dropped at the end of the session or transaction. Any indexes created on temporary tables are temporary as well. See the section . Specify the name of the that describes the placement configuration for this table. By default, tables are placed in the `pg_default` tablespace, which spreads the tablets of the table evenly across the cluster. For hash-sharded tables, you can use the `SPLIT INTO` clause to specify the number of tablets to be created for the table. The hash range is then evenly split across those tablets. Presplitting tablets, using `SPLIT INTO`, distributes write and read workloads on a production cluster. For example, if you have 3 servers, splitting the table into 30 tablets can provide write throughput on the table. For an example, see . {{< note title="Note" >}} By default, YugabyteDB presplits a table in `ysqlnumshardspertserver * numoftserver` shards. The `SPLIT INTO` clause can be used to override that setting on a per-table basis. {{< /note >}} For range-sharded tables, you can use the `SPLIT AT VALUES` clause to set split points to presplit range-sharded tables. Example ```plpgsql CREATE TABLE tbl( a int, b int, primary key(a asc, b desc) ) SPLIT AT VALUES((100), (200), (200, 5)); ``` In the example above, there are three split points and so four tablets will be created: tablet 1: `a=<lowest>, b=<lowest>` to `a=100, b=<lowest>` tablet 2: `a=100, b=<lowest>` to `a=200, b=<lowest>` tablet 3: `a=200, b=<lowest>` to `a=200, b=5` tablet 4: `a=200, b=5` to `a=<highest>, b=<highest>` For colocated databases, specify `false` to opt this table out of colocation. This means that the table won't be stored on the same tablet as the rest of the tables for this database, but instead, will have its own set of tablets. Use this option for large tables that need to be scaled out. See for details on when colocated tables are beneficial. Note that `COLOCATION = true` has no effect if the database that this table is part of is not colocated, as currently colocation is supported only at the database level. Storage parameters, , are ignored and only present for compatibility with PostgreSQL.

yugabyte=# CREATE TABLE sample(k1 int, k2 int, v1 int, v2 text, PRIMARY KEY (k1, k2)); ``` In this example, the first column `k1` will be `HASH`, while second column `k2` will be `ASC`. ```output.sql yugabyte=# \d sample Table "public.sample" Column | Type | Collation | Nullable | Default --++--+-+ k1 | integer | | not null | k2 | integer | | not null | v1 | integer | | | v2 | text | | | Indexes: "sample_pkey" PRIMARY KEY, lsm (k1 HASH, k2) ``` ```plpgsql yugabyte=# CREATE TABLE range(k1 int, k2 int, v1 int, v2 text, PRIMARY KEY (k1 ASC, k2 DESC)); ``` ```plpgsql yugabyte=# CREATE TABLE studentgrade(studentid int, class_id int, term_id int, grade int CHECK (grade >= 0 AND grade <= 10), PRIMARY KEY (studentid, classid, term_id)); ``` ```plpgsql yugabyte=# CREATE TABLE cars(id int PRIMARY KEY, brand text CHECK (brand in ('X', 'Y', 'Z')), model text NOT NULL, color text NOT NULL DEFAULT 'WHITE' CHECK (color in ('RED', 'WHITE', 'BLUE'))); ``` Define two tables with a foreign keys constraint. ```plpgsql yugabyte=# CREATE TABLE products(id int PRIMARY KEY, descr text); yugabyte=# CREATE TABLE orders(id int PRIMARY KEY, pid int REFERENCES products(id) ON DELETE CASCADE, amount int); ``` Insert some rows. ```plpgsql yugabyte=# SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE; yugabyte=# INSERT INTO products VALUES (1, 'Phone X'), (2, 'Tablet Z'); yugabyte=# INSERT INTO orders VALUES (1, 1, 3), (2, 1, 3), (3, 2, 2); yugabyte=# SELECT o.id AS orderid, p.id as productid, p.descr, o.amount FROM products p, orders o WHERE o.pid = p.id; ``` ```output orderid | productid | descr | amount -++-+-- 1 | 1 | Phone X | 3 2 | 1 | Phone X | 3 3 | 2 | Tablet Z | 2 (3 rows) ``` Inserting a row referencing a non-existent product is not allowed. ```plpgsql yugabyte=# INSERT INTO orders VALUES (1, 3, 3); ``` ```output ERROR: insert or update on table "orders" violates foreign key constraint "orderspidfkey" DETAIL: Key (pid)=(3) is not present in table "products". ``` Deleting a product will cascade to all orders (as defined in the `CREATE TABLE` statement above). ```plpgsql yugabyte=# DELETE from products where id = 1; yugabyte=# SELECT o.id AS orderid, p.id as productid, p.descr, o.amount FROM products p, orders o WHERE o.pid = p.id; ``` ```output orderid | productid | descr | amount -++-+-- 3 | 2 | Tablet Z | 2 (1 row) ``` ```plpgsql yugabyte=# CREATE TABLE translations(message_id int UNIQUE, message_txt text); ``` To specify the number of tablets for a table, you can use the `CREATE TABLE` statement with the clause. ```plpgsql yugabyte=# CREATE TABLE tracking (id int PRIMARY KEY) SPLIT INTO 10 TABLETS; ``` ```plpgsql yugabyte=# CREATE DATABASE company WITH COLOCATION = true; yugabyte=# CREATE TABLE employee(id INT PRIMARY KEY, name TEXT) WITH (COLOCATION = false); ``` In this example, database `company` is colocated and all tables other than the `employee` table are stored on a single tablet.