跳转到主要内容
用于更改表结构的一组查询。 语法:
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] [codec] [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 子句,那么即使该列不存在,查询也不会返回错误。 这会从文件系统中删除数据。由于删除的是整个文件,因此查询几乎会立即完成。
如果某列被 materialized view 引用,则无法删除该列。否则会返回错误。
示例:
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] [codec] [TTL] [settings] [AFTER name_after | FIRST]
ALTER COLUMN [IF EXISTS] name TYPE [type] [default_expr] [codec] [TTL] [settings] [AFTER name_after | FIRST]
此查询会更改 name 列的以下属性:
  • 类型
  • 默认表达式
  • 压缩编解码器
  • 生存时间 (TTL)
  • 列级设置
有关修改列压缩编解码器的示例,请参见 列压缩编解码器 有关修改列 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;
┌─name─┬─type───┬
│ c1   │ Int16  │
│ c2   │ String │
└──────┴────────┴

ALTER TABLE users MODIFY COLUMN c2 String FIRST;

DESCRIBE users;
┌─name─┬─type───┬
│ c2   │ String │
│ c1   │ Int16  │
└──────┴────────┴

ALTER TABLE users ALTER COLUMN c2 TYPE String AFTER c1;

DESCRIBE users;
┌─name─┬─type───┬
│ c1   │ Int16  │
│ c2   │ String │
└──────┴────────┴
ALTER 查询具有原子性。对于 MergeTree 表,它还是无锁的。 用于修改列的 ALTER 查询会在副本间复制。相关指令会保存在 ZooKeeper 中,然后由各个副本执行。所有 ALTER 查询都会按相同顺序执行。该查询会等待其他副本上的相应操作完成。不过,对复制表中的列进行修改的查询可能会被中断,而所有操作仍会异步执行。
将 Nullable 列改为 Non-Nullable 时请务必小心。请确保该列中不含任何 NULL 值,否则读取时会出现问题。在这种情况下,可行的处理办法是终止该变更,并将该列改回 Nullable 类型。

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;

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);

┌─groupArray(x)─┬─groupArray(s)─────────┐
│ [0,1,2,3,4]   │ ['0','1','2','3','4'] │
└───────────────┴───────────────────────┘

ALTER TABLE tmp MODIFY COLUMN s String MATERIALIZED toString(round(100/x));

INSERT INTO tmp SELECT * FROM system.numbers LIMIT 5,5;

SELECT groupArray(x), groupArray(s) FROM tmp;

┌─groupArray(x)─────────┬─groupArray(s)──────────────────────────────────┐
│ [0,1,2,3,4,5,6,7,8,9] │ ['0','1','2','3','4','20','17','14','12','11'] │
└───────────────────────┴────────────────────────────────────────────────┘

ALTER TABLE tmp MATERIALIZE COLUMN s;

SELECT groupArray(x), groupArray(s) FROM tmp;

┌─groupArray(x)─────────┬─groupArray(s)─────────────────────────────────────────┐
│ [0,1,2,3,4,5,6,7,8,9] │ ['inf','100','50','33','25','20','17','14','12','11'] │
└───────────────────────┴───────────────────────────────────────────────────────┘
另请参见

限制

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
最后修改于 2026年6月10日