Skip to main content
创建一个新表。默认情况下,表只会在当前服务器上创建。 分布式 DDL 查询通过 ON CLUSTER 子句来实现,相关内容另文说明

语法格式

该查询可根据不同的用例采用多种语法格式。

使用显式 schema 创建表

db 数据库中创建一个名为 table_name 的表;如果未设置 db,则在当前数据库中创建。该表使用括号中指定的结构和 engine 引擎。 表结构由列描述、二级索引、投影和约束组成。如果该引擎支持主键,则会将其标明为表引擎的参数。 最简单情况下,列描述的形式为 name type。示例:RegionID UInt32 类型后面的修饰符——COMMENTcompression_codecSTATISTICSTTLCOLLATEPRIMARY KEY 和按列 SETTINGS——可以按任意顺序编写,并且每个最多只能出现一次。例如,RegionID UInt32 CODEC(ZSTD) COMMENT 'comment for column'RegionID UInt32 COMMENT 'comment for column' CODEC(ZSTD) 是相同的。请注意,SHOW CREATE TABLE 会规范化列声明:其中保留的修饰符始终按规范顺序 COMMENTCODECSTATISTICSTTLCOLLATESETTINGS 输出,而按列 PRIMARY KEY 会从列声明中移至表级 PRIMARY KEY 子句。 也可以为默认值定义表达式 (见下文) 。 如有需要,可以指定主键,其中包含一个或多个键表达式。 可以为列和表添加注释。

使用现有表的 schema 创建表

ClickHouse 支持复制现有表的 schema 和数据。 要复制现有表的 schema: 这会创建一个与另一个表结构相同的表。

使用现有表的 schema 和数据创建表

若要复制现有表的 schema 和数据:
这会创建一个与现有表具有相同 schema 和数据的表。新表创建后,db.table 中的所有分区都会附加到该表。换句话说,在创建时,db.table 的数据会被克隆到 db2.table_clone。该查询等同于以下内容:
对于这两项功能,你都可以为该表指定不同的引擎。如果未指定引擎,则默认使用与原始表 (db.table) 相同的引擎。

使用表函数创建表

创建一个表,其结果与指定的表函数相同。创建后的表也会像所指定的对应表函数一样工作。

使用 SELECT 查询创建表

使用 engine 引擎创建一个表,其结构与 SELECT 查询结果类似,并使用 SELECT 的数据填充该表。你也可以显式指定列描述。 如果表已存在且指定了 IF NOT EXISTS,则该查询不会执行任何操作。 查询中在 ENGINE 子句之后还可以有其他子句。有关如何创建表的详细文档,请参阅表引擎说明。 示例
Query
Response

指定列默认值

列描述可以通过 DEFAULT exprMATERIALIZED exprALIAS expr 的形式指定默认值表达式。例如:URLDomain String DEFAULT domain(URL) 表达式 expr 是可选的。如果省略,则必须显式指定列类型,此时默认值分别为:数值列为 0,字符串列为 '' (空字符串) ,数组列为 [] (空数组) ,日期列为 1970-01-01,Nullable 列为 NULL 默认值列的列类型可以省略,这种情况下会根据 expr 的类型自动推断。例如,列 EventDate DEFAULT toDate(EventTime) 的类型将为日期类型。 如果同时指定了 数据类型 和默认值表达式,系统会插入一个隐式类型转换函数,将表达式转换为指定类型。例如:Hits UInt32 DEFAULT 0 在内部会表示为 Hits UInt32 DEFAULT toUInt32(0) 默认值表达式 expr 可以引用任意表列和常量。ClickHouse 会检查对表结构的修改不会在表达式计算中引入循环。对于 INSERT,它还会检查这些表达式是否可解析——也就是说,用于计算它们的所有列都必须已传入。

DEFAULT

DEFAULT expr 普通默认值。如果在 INSERT 查询中未指定此类列的值,则会根据 expr 计算。 示例:

MATERIALIZED

MATERIALIZED expr 物化表达式。插入行时,这类列的值会根据指定的物化表达式自动计算,不能在 INSERT 时显式指定。 此外,此类默认值列不会包含在 SELECT * 的结果中。这是为了保持这样一个不变性:SELECT * 的结果始终都可以通过 INSERT 再次插入到表中。可通过设置 asterisk_include_materialized_columns 禁用此行为。 示例:

EPHEMERAL

EPHEMERAL [expr] 临时列。此类型的列不会存储在表中,也无法对其执行 SELECT。临时列的唯一用途,是基于它们构建其他列的默认值表达式。 执行未显式指定列的插入时,会跳过此类型的列。这样做是为了保持这样一个不变性:SELECT * 的结果始终都可以通过 INSERT 再次插回表中。 示例:

ALIAS

ALIAS expr 计算列 (同义概念) 。这种类型的列不会存储在表中,也无法向其中 INSERT 值。 SELECT 查询显式引用这种类型的列时,其值会在查询时根据 expr 计算。默认情况下,SELECT * 会排除 ALIAS 列。可通过设置 asterisk_include_alias_columns 禁用此行为。 使用 ALTER 查询添加新列时,不会为这些列补写旧数据。相反,在读取不包含这些新列值的旧数据时,默认会动态计算表达式。不过,如果计算这些表达式需要查询中未指出的其他列,则还会额外读取这些列,但仅限于需要它们的数据块。 如果向表中添加了一个新列,但之后又更改了它的默认表达式,那么旧数据使用的值也会发生变化 (即那些值未存储在磁盘上的数据) 。请注意,在执行后台合并时,如果参与合并的某个 parts 中缺少某列的数据,则会将该列的数据写入合并后的 part。 无法为嵌套数据结构中的元素设置默认值。

使用 NULL 或 NOT NULL 修饰符

在列定义中,数据类型后面的 NULLNOT NULL 修饰符用于控制该列是否可以为 Nullable 如果该类型不是 Nullable,并且指定了 NULL,则会将其视为 Nullable;如果指定了 NOT NULL,则不会。例如,INT NULL 等同于 Nullable(INT)。如果该类型本身就是 Nullable,再指定 NULLNOT NULL 修饰符时,则会抛出异常。 另请参见 data_type_default_nullable 设置。

主键

你可以在创建表时定义主键。主键可以通过两种方式指定:
在列列表中
不在列列表中
不能在一次查询中同时使用这两种方式。

指定表约束

除列描述外,还可以定义约束:

CONSTRAINT

boolean_expr_1 可以是任意布尔表达式。如果为该表定义了约束,那么在执行 INSERT 查询时,每一行都会检查所有约束。如果有任何约束不满足,server 将抛出异常,并给出约束名称和检查表达式。 添加大量约束可能会对大型 INSERT 查询的性能产生负面影响。 可以通过 system.constraints 表查看所有表中现有的约束。

ASSUME

ASSUME 子句用于在表上定义一个被假定为真的 CONSTRAINT。优化器随后可以利用该约束来提升 SQL 查询性能。 以下示例展示了在创建 users_a 表时如何使用 ASSUME CONSTRAINT
这里,ASSUME CONSTRAINT 用于断言 length(name) 函数的结果始终等于 name_len 列的值。这意味着,每当在查询中调用 length(name) 时,ClickHouse 都可以将其替换为 name_len,这样通常会更快,因为不必调用 length() 函数。 随后,在执行查询 SELECT name FROM users_a WHERE length(name) < 5; 时,ClickHouse 可以根据 ASSUME CONSTRAINT 将其优化为 SELECT name FROM users_a WHERE name_len < 5;。这样可以让查询运行得更快,因为无需为每一行计算 name 的长度。 ASSUME CONSTRAINT 不会强制执行该约束,它只是告知优化器该约束成立。如果该约束实际上并不成立,查询结果可能会不正确。因此,只有在你确定该约束确实成立时,才应使用 ASSUME CONSTRAINT

使用 TTL 定义存储时长

定义值的存储时长。只能为 MergeTree 家族表指定。有关详细说明,请参阅列和表的 TTL

选择列压缩编解码器

默认情况下,自管理版本的 ClickHouse 使用 lz4 压缩,ClickHouse Cloud 则使用 zstd。您还可以在 CREATE TABLE 查询中为每一列指定压缩方法:
有关可用的通用、专用和加密编解码器,请参阅列压缩编解码器

创建临时表

ClickHouse 支持临时表,会话结束后这些表将自动消失。详情请参阅 CREATE TEMPORARY TABLE

使用 REPLACE TABLE 以原子方式更新表

REPLACE 语句允许你以原子方式更新表。有关详细信息,请参阅 REPLACE TABLE

添加表注释

您可以在创建表时添加注释。 语法
COMMENT 子句必须在 PARTITION BYORDER BY 以及存储专用 SETTINGS 等所有存储相关子句之后指定。COMMENT 子句之后,只会解析查询专用 SETTINGS (如 max_threads 等) ,不会解析存储相关设置。这意味着,正确的子句顺序是:
  • ENGINE
  • 存储子句
  • COMMENT
  • 查询设置 (如有)
示例
Query
Response
最后修改于 2026年8月14日