Skip to content
ClickHouse Docs
ClickHouse DocsClickHouse Docs

ALTER TABLE ... COLUMN

用于更改表结构的一组查询。

语法:

ALTER [TEMPORARY] TABLE [db].name [ON CLUSTER cluster] ADD|DROP|RENAME|CLEAR|COMMENT|{MODIFY|ALTER}|MATERIALIZE COLUMN ...

在查询中,指定一个由一个或多个以逗号分隔的操作组成的列表。 每个操作都是对某一列执行的一项操作。

支持以下操作:

ADD COLUMN

ADD COLUMN [IF NOT EXISTS] name [type] [default_expr] [COMMENT 'comment for column'] [codec] [STATISTICS] [TTL] [settings] [AFTER name_after | FIRST]

向表中添加一个具有指定 nametypecodecdefault_expr 的新列 (参见 默认表达式 一节) 。类型后面的修饰符可以按任意顺序编写,且每个修饰符最多只能出现一次——参见 列描述

如果包含 IF NOT EXISTS 子句,那么即使该列已存在,查询也不会返回错误。如果指定了 AFTER name_after (另一个列的名称) ,则会将该列添加到表列列表中指定列的后面。如果要将列添加到表的开头,请使用 FIRST 子句。否则,该列会被添加到表的末尾。对于一系列操作,name_after 也可以是前一个操作中添加的列名。

添加列只会更改表结构,不会对数据执行任何操作。ALTER 之后,数据不会立即出现在磁盘上。如果从表中读取时某列的数据缺失,则会使用默认值填充 (如果存在默认表达式则执行它,否则使用零值或空字符串) 。该列会在数据分区片段合并后出现在磁盘上 (参见 MergeTree) 。

这种方式使我们能够立即完成 ALTER 查询,而不会增加旧数据的体量。

示例:

ALTER TABLE alter_test ADD COLUMN Added1 UInt32 FIRST;
ALTER TABLE alter_test ADD COLUMN Added2 UInt32 AFTER NestedColumn;
ALTER TABLE alter_test ADD COLUMN Added3 UInt32 AFTER ToDrop;
DESC alter_test FORMAT TSV;
Added1  UInt32
CounterID       UInt32
StartDate       Date
UserID  UInt32
VisitID UInt32
NestedColumn.A  Array(UInt8)
NestedColumn.S  Array(String)
Added2  UInt32
ToDrop  UInt32
Added3  UInt32

DROP COLUMN

DROP COLUMN [IF EXISTS] name

删除名为 name 的列。如果指定了 IF EXISTS 子句,那么即使该列不存在,查询也不会返回错误。

这会从文件系统中删除数据。由于删除的是整个文件,因此查询几乎会立即完成。

示例:

ALTER TABLE visits DROP COLUMN browser

RENAME COLUMN

RENAME COLUMN [IF EXISTS] name to new_name

将列 name 重命名为 new_name。如果指定了 IF EXISTS 子句,即使该列不存在,查询也不会报错。由于重命名不涉及底层数据,因此该查询几乎会立即完成。

注意:表的键表达式中指定的列 (无论是通过 ORDER BY 还是 PRIMARY KEY 指定) 都不能重命名。尝试修改这些列会产生 SQL Error [524]

示例:

ALTER TABLE visits RENAME COLUMN webBrowser TO browser

CLEAR COLUMN

CLEAR COLUMN [IF EXISTS] name IN PARTITION partition_name

重置指定分区中某列的所有数据。有关如何设置分区名称,请参阅如何设置分区表达式一节。

如果指定了 IF EXISTS 子句,则当该列不存在时,查询不会报错。

示例:

ALTER TABLE visits CLEAR COLUMN browser IN PARTITION tuple()

COMMENT COLUMN

COMMENT COLUMN [IF EXISTS] name 'Text comment'

为该列添加注释。如果指定了 IF EXISTS 子句,则当该列不存在时,查询也不会返回错误。

每列只能有一条注释。如果该列已有注释,新的注释会覆盖之前的注释。

注释存储在 DESCRIBE TABLE 查询返回结果的 comment_expression 列中。

示例:

ALTER TABLE visits COMMENT COLUMN browser 'This column shows the browser used for accessing the site.'

MODIFY COLUMN

MODIFY COLUMN [IF EXISTS] name
    [type] [default_expr] [COMMENT 'comment for column'] [codec] [STATISTICS] [TTL] [settings] [AFTER name_after | FIRST]
    | ADD ENUM VALUES ( 'name' [= number] [, ...] )
ALTER COLUMN [IF EXISTS] name
    TYPE [type] [default_expr] [COMMENT 'comment for column'] [codec] [STATISTICS] [TTL] [settings] [AFTER name_after | FIRST]
    | ADD ENUM VALUES ( 'name' [= number] [, ...] )

类型后面的修饰符可按任意顺序书写,且每种最多只能出现一次——参见列描述

此查询会更改 name 列的以下属性:

  • 类型

  • 默认表达式

  • 压缩编解码器

  • 生存时间 (TTL)

  • 列级设置

  • Enum/Enum8/Enum16 类型的枚举值

有关修改列压缩编解码器的示例,请参见 列压缩编解码器

有关修改列生存时间 (TTL) 的示例,请参见 列 TTL

有关修改列级设置的示例,请参见 列级设置

如果指定了 IF EXISTS 子句,则当该列不存在时,查询不会报错。

更改类型时,值会按对其应用 toType 函数后的方式进行转换。如果仅更改默认表达式,查询不会执行任何复杂操作,几乎会立即完成。

示例:

ALTER TABLE visits MODIFY COLUMN browser Array(String)

更改列类型是唯一较为复杂的操作——它会改动数据文件中的内容。对于大型表,这可能需要很长时间。

该查询还可以使用 FIRST | AFTER 子句更改列的顺序,参见 ADD COLUMN 的说明,但在这种情况下必须指定列类型。

示例:

CREATE TABLE users (
    c1 Int16,
    c2 String
) ENGINE = MergeTree
ORDER BY c1;

DESCRIBE users;

ALTER 查询具有原子性。对于 MergeTree 表,它还是无锁的。

用于修改列的 ALTER 查询会在副本间复制。相关指令会保存在 ZooKeeper 中,然后由各个副本执行。所有 ALTER 查询都会按相同顺序执行。该查询会等待其他副本上的相应操作完成。不过,对复制表中的列进行修改的查询可能会被中断,而所有操作仍会异步执行。

MODIFY COLUMN REMOVE

移除以下列属性之一:DEFAULTALIASMATERIALIZEDCODECCOMMENTTTLSETTINGS

语法:

ALTER TABLE table_name MODIFY COLUMN column_name REMOVE property;

示例

移除生存时间 (TTL):

ALTER TABLE table_with_ttl MODIFY COLUMN column_ttl REMOVE TTL;

另见

MODIFY COLUMN MODIFY SETTING

修改列的设置。

语法:

ALTER TABLE table_name MODIFY COLUMN column_name MODIFY SETTING name=value,...;

示例

将该列的 max_compress_block_size 修改为 1MB

ALTER TABLE table_name MODIFY COLUMN column_name MODIFY SETTING max_compress_block_size = 1048576;

MODIFY COLUMN RESET SETTING

重置列设置,同时也会移除该表 CREATE 查询中列表达式里的设置声明。

语法:

ALTER TABLE table_name MODIFY COLUMN column_name RESET SETTING name,...;

示例

将列设置 max_compress_block_size 重置为默认值:

ALTER TABLE table_name MODIFY COLUMN column_name RESET SETTING max_compress_block_size;

MODIFY COLUMN ADD ENUM VALUES

为类型为 EnumEnum8Enum16Nullable(Enum)Nullable(Enum8)Nullable(Enum16) 的列添加新值

语法:

ALTER TABLE table_name MODIFY COLUMN enum_column_name ADD ENUM VALUES ('EnumName' [= number], ...);

示例

enum_column_name 列中添加两个值:

ALTER TABLE table_name MODIFY COLUMN enum_column_name ADD ENUM VALUES ('Hundred' = 100, 'HundredOne');

MATERIALIZE COLUMN

将具有 DEFAULTMATERIALIZED 值表达式的列物化。使用 ALTER TABLE table_name ADD COLUMN column_name MATERIALIZED 添加物化列时,现有行中缺失的物化值不会自动补齐。添加或更新 DEFAULTMATERIALIZED 表达式后,MATERIALIZE COLUMN 语句可用于重写现有列数据 (因为这类操作只会更新元数据,不会更改现有数据) 。请注意,对排序键中的列执行物化是无效操作,因为这可能会破坏排序顺序。 其实现方式为 变更

对于具有新的或已更新 MATERIALIZED 值表达式的列,所有现有行都会被重写。

对于具有新的或已更新 DEFAULT 值表达式的列,其行为取决于 ClickHouse 版本:

  • 在 ClickHouse < v24.2 中,所有现有行都会被重写。
  • ClickHouse >= v24.2 会区分带有 DEFAULT 值表达式的列中,某一行的值是在插入时显式指定的,还是由 DEFAULT 值表达式计算得出的。若该值是显式指定的,ClickHouse 会保持原样。若该值是计算得出的,ClickHouse 会将其更改为新的或已更新的 MATERIALIZED 值表达式。

语法:

ALTER TABLE [db.]table [ON CLUSTER cluster] MATERIALIZE COLUMN col [IN PARTITION partition | IN PARTITION ID 'partition_id'];
  • 如果指定了 PARTITION,则仅会物化指定分区中的该列。

示例

DROP TABLE IF EXISTS tmp;
SET mutations_sync = 2;
CREATE TABLE tmp (x Int64) ENGINE = MergeTree() ORDER BY tuple() PARTITION BY tuple();
INSERT INTO tmp SELECT * FROM system.numbers LIMIT 5;
ALTER TABLE tmp ADD COLUMN s String MATERIALIZED toString(x);

ALTER TABLE tmp MATERIALIZE COLUMN s;

SELECT groupArray(x), groupArray(s) FROM (select x,s from tmp order by x);

另请参阅

限制

ALTER 查询允许在嵌套数据结构中创建和删除单个元素 (列) ,但不支持创建或删除整个嵌套数据结构。要添加嵌套数据结构,可以添加名称类似 name.nested_name、类型为 Array(T) 的列。嵌套数据结构等价于多个数组列,这些列的名称在点号前具有相同的前缀。

对名称中带点的列进行重命名仅部分受支持。点号保留用于访问 Nested 子列,因此前缀 (父级名称) 必须保持不变。只有后缀 (子列名称) 可以更改。例如,a.b 可以重命名为 a.c,但不允许将 a.b 重命名为 b.d,因为这会更改 Nested 父级前缀。

不支持删除主键或采样键中的列 (即在 ENGINE 表达式中使用的列) 。只有在不会导致数据发生修改的情况下,才可以更改包含在主键中的列的类型 (例如,可以向 Enum 添加值,或将类型从 DateTime 更改为 UInt32) 。

如果 ALTER 查询不足以完成所需的表更改,可以创建一个新表,使用 INSERT SELECT 查询将数据复制到该表,然后使用 RENAME 查询切换表,并删除旧表。

ALTER 查询会阻塞该表上的所有读写。换句话说,如果在执行 ALTER 查询时有一个长时间运行的 SELECT 查询,ALTER 查询会等待其完成。同时,在此次 ALTER 执行期间,对同一张表发起的所有新查询也都会等待。

对于不自行存储数据的表 (例如 MergeDistributed) ,ALTER 只会更改表结构,而不会更改下级表的结构。例如,对 Distributed 表执行 ALTER 时,还需要对所有远程服务器上的表执行 ALTER

Navigation