约束概述¶
Snowflake 提供以下约束功能:
源自 ANSI SQL 标准的约束类型。有关更多信息,请参阅 支持的约束类型。
命名约束。
单列和多列约束。
创建内联和外联约束。
创建、修改和删除约束。
有关更多信息,请参阅 CREATE | ALTER TABLE ... CONSTRAINT。
支持的约束类型¶
Snowflake 支持 ANSI SQL 标准中的以下约束类型:
PRIMARY KEY:确保列中的所有值都是唯一的,且该列不能存储 NULL 值。主键唯一标识表中的每一行。
UNIQUE:确保列中的所有值都是唯一的。与 PRIMARY KEY 约束不同,带有 UNIQUE 约束的列可以包含 NULL 值。
FOREIGN KEY:通过要求一列或一组列中的值与另一个表或同一个表中的值相匹配,来强制执行参照完整性。
NOT NULL:确保列不能存储 NULL 值。
CHECK:强制执行 SQL 表达式,将其作为可插入或更新到表的一个或多个列中的值的条件。有关更多信息,请参阅 CHECK 约束。
一个表可以有多个唯一键和外键,但只能有一个主键。PRIMARY KEY 约束意味着列既是 NOT NULL 也是 UNIQUE。
所有外键都必须引用与外键中每列的列类型匹配的相应主键或唯一键。外键的相应主键可以与外键位于不同或相同的表上。在跨 混合表 定义 FOREIGN KEY 约束时,这些表必须位于同一数据库中。
下表总结了标准表和混合表之间在约束的执行以及是否需要约束方面的行为差异:
当约束条件保护列不以某些方式更新时,该约束条件被 强制执行。例如,声明为 NOT NULL 的列不能包含 NULL 值。尝试将 NULL 值复制或插入到 NOT NULL 列会导致错误。对于混合表,不能在 PRIMARY KEY、FOREIGN KEY 和 UNIQUE 约束条件上设置 NOT ENFORCED 属性。设置此属性会导致
invalid constraint property错误。当表中的一个或多个列必须具有这样的约束条件时,约束条件则是 必需的,仅对混合表的 PRIMARY KEY 约束条件有效。
功能 |
混合表 |
标准表 |
|---|---|---|
PRIMARY KEY 约束 |
必需,已强制执行 |
可选,未强制执行 |
FOREIGN KEY 约束 |
可选、已强制执行(参照完整性) |
可选,未强制执行 |
UNIQUE 约束 |
可选,已强制执行 |
可选,未强制执行 |
NOT NULL 约束 |
可选,已强制执行 |
可选,已强制执行 |
CHECK 约束 |
不支持 |
可选,已强制执行 |
表约束条件¶
Snowflake 支持对永久表、瞬态表、临时表和混合表的约束。可以对所有数据类型的列定义约束,并且可以在单个约束中包括任意数量的列。
以下是约束的注意事项:
在使用 CREATE TABLE ... LIKE 或 CREATE TABLE ... CLONE 复制表时,则表上的所有现有约束(包括外键)都将复制到新表中(混合表不支持 CREATE TABLE ... CLONE)。
具有约束的表还支持其他命令和函数,例如 DROP、UNDROP 和 GET_DDL。架构和数据库也支持它们。
对于 Snowflake Time Travel,如果复制表的先前版本,则会使用表的当前版本约束,因为 Snowflake 不会在表元数据中存储以前版本的约束。
单列和多列约束¶
您可以在同一表中的单列或多列上定义约束。
对于多列约束(复合主键或唯一键),列是有序的,每列都有相应的键序列。
内联和外联约束¶
约束可以在表创建或修改期间以内联或外联方式进行定义:
内联约束作为列定义的一部分创建,只能用于单列约束。
外联约束使用单独的子句定义,该子句指定了创建约束的列。外联约束可用于创建单列或多列约束,还可用于在现有列上创建约束。
GET_DDL 约束¶
GET_DDL 返回的 SQL 语句包括定义约束的子句。但是,请注意以下几点:
单列约束(如
NOT NULL和DEFAULT)是根据列的定义重新构造的内联。表约束(如唯一键、主键、外键)始终被重新构造为外联约束,即使它们由单个列组成也是如此。
对于未命名的约束(即具有系统生成名称的约束),GET_DDL 不会返回系统生成的名称。
CHECK 约束¶
CHECK 约束强制执行 SQL 表达式,将其作为可插入或更新到表的一个或多个列中的值的条件。例如,CHECK 约束可以确保表中的 quantity 列仅包含大于零的值,或者表中的 salary 列仅包含特定范围内的值。
您可以通过在以下 SQL 命令中使用 CONSTRAINT 子句 来指定 CHECK 约束:
您可以通过查询 CHECK_CONSTRAINTS 视图 来显示有关现有 CHECK 约束的信息。
在以下 DML 操作期间会强制执行 Check 约束:
如果条件的评估结果为 TRUE 或 NULL,则继续执行 DML 操作。如果条件的评估结果为 FALSE,则 CHECK 约束失败。
有关 CHECK 约束的示例,请参阅 标准表的约束示例。
使用说明¶
Check 约束始终会被强制执行。
您可以使用以下 ALTER TABLE 命令和 Iceberg 等效命令来处理 CHECK 约束:
ALTER TABLE ... RENAME CONSTRAINT
ALTER TABLE ... ADD [ CONSTRAINT <constraint_name> ] CHECK ( <expr> ) ENABLE [ VALIDATE | NOVALIDATE ]
ENABLE VALIDATE 是 CHECK 约束的默认设置,它对所有现有行以及运行命令后插入或更新的所有行强制执行约束。ENABLE VALIDATE 仅支持新表,不支持现有表。
ENABLE NOVALIDATE 对运行命令后插入或更新的所有行强制执行约束,但不针对现有行强制执行约束。
ALTER TABLE ... ALTER CONSTRAINT <constraint_name> ENABLE [ VALIDATE | NOVALIDATE ]
如果您将 CHECK 约束从 NOVALIDATE 更改为 VALIDATE,则在更改为 VALIDATE 之前,会对所有现有行强制执行该约束。
ALTER TABLE ... DROP CONSTRAINT
以下 ALTER TABLE 命令和 Iceberg 等效命令可以操作定义了 CHECK 约束的列:
ALTER TABLE ...ALTER COLUMN
仅支持不修改 CHECK 约束的操作。
ALTER TABLE ...RENAME COLUMN
引用了重命名列的 Check 约束会自动更新以使用新的列名。
ALTER TABLE ... DROP COLUMN
如果正在删除的列被现有的 CHECK 约束使用,且该约束还引用了另一列,则操作失败。在这种情况下,请在删除列之前先删除该约束。
如果记录在引入过程中违反了 CHECK 约束,则批量操作在第一次遇到无效记录时就会失败。
限制¶
仅标准表和 Snowflake 管理的 Iceberg 表支持 CHECK 约束条件。其他类型的表(例如混合表)不支持 CHECK 约束。
无法使用 ALTER TABLE 命令修改与现有 CHECK 约束关联的表达式。要修改表达式,请删除并重新创建该 CHECK 约束。
不能在 CREATE OR ALTER TABLE 命令中指定 CHECK 约束。
以下操作不支持 CHECK 约束:
如果您尝试对带有 CHECK 约束的表执行 COPY INTO,则操作失败。
如果您尝试向具有 CHECK 约束的目标表创建管道,该操作将失败。
如果您尝试向具有 CHECK 约束的表进行流式引入,该操作将失败。
如果您尝试对具有 CHECK 约束的 Iceberg 表进行外部写入,该操作将失败。