CREATE TABLE
Creates a new table. This query can have various syntax forms depending on a use case.
By default, tables are created only on the current server. Distributed DDL queries are implemented as ON CLUSTER
clause, which is described separately.
Syntax Forms
With Explicit Schema
CREATE TABLE [IF NOT EXISTS] [db.]table_name [ON CLUSTER cluster]
(
name1 [type1] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|EPHEMERAL|ALIAS expr1] [COMMENT 'comment for column'] [compression_codec] [TTL expr1],
name2 [type2] [NULL|NOT NULL] [DEFAULT|MATERIALIZED|EPHEMERAL|ALIAS expr2] [COMMENT 'comment for column'] [compression_codec] [TTL expr2],
...
) ENGINE = engine
[COMMENT 'comment for table']
Creates a table named table_name
in the db
database or the current database if db
is not set, with the structure specified in brackets and the engine
engine.
The structure of the table is a list of column descriptions, secondary indexes and constraints . If primary key is supported by the engine, it will be indicated as parameter for the table engine.
A column description is name type
in the simplest case. Example: RegionID UInt32
.
Expressions can also be defined for default values (see below).
If necessary, primary key can be specified, with one or more key expressions.
Comments can be added for columns and for the table.
With a Schema Similar to Other Table
CREATE TABLE [IF NOT EXISTS] [db.]table_name AS [db2.]name2 [ENGINE = engine]
Creates a table with the same structure as another table. You can specify a different engine for the table. If the engine is not specified, the same engine will be used as for the db2.name2
table.
With a Schema and Data Cloned from Another Table
CREATE TABLE [IF NOT EXISTS] [db.]table_name CLONE AS [db2.]name2 [ENGINE = engine]
Creates a table with the same structure as another table. You can specify a different engine for the table. If the engine is not specified, the same engine will be used as for the db2.name2
table. After the new table is created, all partitions from db2.name2
are attached to it. In other words, the data of db2.name2
is cloned into db.table_name
upon creation. This query is equivalent to the following:
CREATE TABLE [IF NOT EXISTS] [db.]table_name AS [db2.]name2 [ENGINE = engine];
ALTER TABLE [db.]table_name ATTACH PARTITION ALL FROM [db2].name2;
From a Table Function
CREATE TABLE [IF NOT EXISTS] [db.]table_name AS table_function()
Creates a table with the same result as that of the table function specified. The created table will also work in the same way as the corresponding table function that was specified.
From SELECT query
CREATE TABLE [IF NOT EXISTS] [db.]table_name[(name1 [type1], name2 [type2], ...)] ENGINE = engine AS SELECT ...
Creates a table with a structure like the result of the SELECT
query, with the engine
engine, and fills it with data from SELECT
. Also you can explicitly specify columns description.
If the table already exists and IF NOT EXISTS
is specified, the query won't do anything.
There can be other clauses after the ENGINE
clause in the query. See detailed documentation on how to create tables in the descriptions of table engines.
In ClickHouse Cloud please split this into two steps:
- Create the table structure
CREATE TABLE t1
ENGINE = MergeTree
ORDER BY ...
# highlight-next-line
EMPTY AS
SELECT ...
- Populate the table
INSERT INTO t1
SELECT ...
Example
Query:
CREATE TABLE t1 (x String) ENGINE = Memory AS SELECT 1;
SELECT x, toTypeName(x) FROM t1;
Result:
┌─x─┬─toTypeName(x)─┐
│ 1 │ String │
└───┴───────────────┘
NULL Or NOT NULL Modifiers
NULL
and NOT NULL
modifiers after data type in column definition allow or do not allow it to be Nullable.
If the type is not Nullable
and if NULL
is specified, it will be treated as Nullable
; if NOT NULL
is specified, then no. For example, INT NULL
is the same as Nullable(INT)
. If the type is Nullable
and NULL
or NOT NULL
modifiers are specified, the exception will be thrown.
See also data_type_default_nullable setting.
Default Values
The column description can specify a default value expression in the form of DEFAULT expr
, MATERIALIZED expr
, or ALIAS expr
. Example: URLDomain String DEFAULT domain(URL)
.
The expression expr
is optional. If it is omitted, the column type must be specified explicitly and the default value will be 0
for numeric columns, ''
(the empty string) for string columns, []
(the empty array) for array columns, 1970-01-01
for date columns, or NULL
for nullable columns.
The column type of a default value column can be omitted in which case it is inferred from expr
's type. For example the type of column EventDate DEFAULT toDate(EventTime)
will be date.
If both a data type and a default value expression are specified, an implicit type casting function inserted which converts the expression to the specified type. Example: Hits UInt32 DEFAULT 0
is internally represented as Hits UInt32 DEFAULT toUInt32(0)
.
A default value expression expr
may reference arbitrary table columns and constants. ClickHouse checks that changes of the table structure do not introduce loops in the expression calculation. For INSERT, it checks that expressions are resolvable – that all columns they can be calculated from have been passed.
DEFAULT
DEFAULT expr
Normal default value. If the value of such a column is not specified in an INSERT query, it is computed from expr
.
Example:
CREATE OR REPLACE TABLE test
(
id UInt64,
updated_at DateTime DEFAULT now(),
updated_at_date Date DEFAULT toDate(updated_at)
)
ENGINE = MergeTree
ORDER BY id;
INSERT INTO test (id) Values (1);
SELECT * FROM test;
┌─id─┬──────────updated_at─┬─updated_at_date─┐
│ 1 │ 2023-02-24 17:06:46 │ 2023-02-24 │
└────┴─────────────────────┴─────────────────┘
MATERIALIZED
MATERIALIZED expr
Materialized expression. Values of such columns are automatically calculated according to the specified materialized expression when rows are inserted. Values cannot be explicitly specified during INSERT
s.
Also, default value columns of this type are not included in the result of SELECT *
. This is to preserve the invariant that the result of a SELECT *
can always be inserted back into the table using INSERT
. This behavior can be disabled with setting asterisk_include_materialized_columns
.
Example:
CREATE OR REPLACE TABLE test
(
id UInt64,
updated_at DateTime MATERIALIZED now(),
updated_at_date Date MATERIALIZED toDate(updated_at)
)
ENGINE = MergeTree
ORDER BY id;
INSERT INTO test Values (1);
SELECT * FROM test;
┌─id─┐
│ 1 │
└────┘
SELECT id, updated_at, updated_at_date FROM test;
┌─id─┬──────────updated_at─┬─updated_at_date─┐
│ 1 │ 2023-02-24 17:08:08 │ 2023-02-24 │
└────┴─────────── ──────────┴─────────────────┘
SELECT * FROM test SETTINGS asterisk_include_materialized_columns=1;
┌─id─┬──────────updated_at─┬─updated_at_date─┐
│ 1 │ 2023-02-24 17:08:08 │ 2023-02-24 │
└────┴─────────────────────┴─────────────────┘
EPHEMERAL
EPHEMERAL [expr]
Ephemeral column. Columns of this type are not stored in the table and it is not possible to SELECT from them. The only purpose of ephemeral columns is to build default value expressions of other columns from them.
An insert without explicitly specified columns will skip columns of this type. This is to preserve the invariant that the result of a SELECT *
can always be inserted back into the table using INSERT
.
Example:
CREATE OR REPLACE TABLE test
(
id UInt64,
unhexed String EPHEMERAL,
hexed FixedString(4) DEFAULT unhex(unhexed)
)
ENGINE = MergeTree
ORDER BY id;
INSERT INTO test (id, unhexed) Values (1, '5a90b714');
SELECT
id,
hexed,
hex(hexed)
FROM test
FORMAT Vertical;
Row 1:
──────
id: 1
hexed: Z��
hex(hexed): 5A90B714
ALIAS
ALIAS expr
Calculated columns (synonym). Column of this type are not stored in the table and it is not possible to INSERT values into them.
When SELECT queries explicitly reference columns of this type, the value is computed at query time from expr
. By default, SELECT *
excludes ALIAS columns. This behavior can be disabled with setting asterisk_include_alias_columns
.
When using the ALTER query to add new columns, old data for these columns is not written. Instead, when reading old data that does not have values for the new columns, expressions are computed on the fly by default. However, if running the expressions requires different columns that are not indicated in the query, these columns will additionally be read, but only for the blocks of data that need it.
If you add a new column to a table but later change its default expression, the values used for old data will change (for data where values were not stored on the disk). Note that when running background merges, data for columns that are missing in one of the merging parts is written to the merged part.
It is not possible to set default values for elements in nested data structures.
CREATE OR REPLACE TABLE test
(
id UInt64,
size_bytes Int64,
size String ALIAS formatReadableSize(size_bytes)
)
ENGINE = MergeTree
ORDER BY id;
INSERT INTO test VALUES (1, 4678899);
SELECT id, size_bytes, size FROM test;
┌─id─┬─size_bytes─┬─size─────┐
│ 1 │ 4678899 │ 4.46 MiB │
└────┴────────────┴──────────┘
SELECT * FROM test SETTINGS asterisk_include_alias_columns=1;
┌─id─┬─size_bytes─┬─size─────┐
│ 1 │ 4678899 │ 4.46 MiB │
└────┴────────────┴──────────┘