创建和管理检查约束条件

借助 CHECK 限制条件,您可以指定一个或多个列的值必须满足布尔值表达式。在本文中,我们将介绍如何在数据库中管理此类限制条件。

向新表添加检查约束条件

在以下 CREATE TABLE 代码段中,我们将创建一个表来存储音乐会的相关信息。为了使音乐会的结束时间晚于开始时间,我们添加了检查限制条件。

GoogleSQL

CREATE TABLE Concerts (
  ConcertId INT64,
  StartTime Timestamp,
  EndTime Timestamp,
  CONSTRAINT start_before_end CHECK(StartTime < EndTime),
) PRIMARY KEY (ConcertId);

PostgreSQL

CREATE TABLE Concerts (
  ConcertId BIGINT,
  StartTime TIMESTAMPTZ,
  EndTime TIMESTAMPTZ,
  CONSTRAINT start_before_end CHECK(StartTime < EndTime),
  PRIMARY KEY (ConcertId)
);

限制条件的定义从 CONSTRAINT 关键字开始。在此示例中,我们将该限制条件明确命名为 start_before_end,因此可以在错误消息中以及在需要引用它时很容易识别它。如果拒绝 则 Spanner 会提供一个,其生成名称以 前缀为 CK_。限制条件名称的范围限定为架构以及表和索引的名称,并且在架构内必须具有唯一性。检查限制条件定义包括关键字 CHECK 和括号中的表达式。表达式只能引用此表的列。在此示例中,它引用了 StartTimeEndTime,因此在这里进行检查可确保音乐会的开始时间始终小于结束时间。

插入新行或更新现有行的 StartTimeEndTime 时,会计算检查限制条件表达式的值。如果表达式的计算结果为 TRUENULL,则检查限制条件会允许更改数据。如果表达式的计算结果为 FALSE,则不允许更改数据。

  • 以下限制适用于检查限制条件 expression 术语。

    • 表达式只能引用同一表中的列。

    • 表达式必须直接引用至少一个非生成的列,无论是直接引用,还是通过引用非生成的列的生成的列进行引用。

    • 表达式无法引用已设置 allow_commit_timestamp 选项的列。

    • 表达式不能包含子查询

    • 表达式不能包含非确定性函数,例如 CURRENT_DATE()CURRENT_TIMESTAMP()

向现有表添加检查限制条件

我们使用以下 ALTER TABLE 语句添加一个约束条件,以确保 所有音乐会 ID 都大于零。

ALTER TABLE Concerts
ADD CONSTRAINT concert_id_gt_0 CHECK (ConcertId > 0);

同样,我们已将该限制条件命名为 concert_id_gt_0。向现有表添加 CHECK 限制条件会立即开始对新数据强制执行该限制条件,并启动长时间运行的操作以验证现有数据是否符合新的限制条件。由于此验证是以长时间运行的操作执行的,因此对表持续进行的事务不会受到影响。如需了解详情,请参阅架构更新性能。如果现有数据存在任何违规情况,则会回滚该限制条件。

移除检查限制条件

以下 DDL 语句删除 Concerts 表中的 CHECK 限制条件。

ALTER TABLE Concerts
DROP CONSTRAINT concert_id_gt_0;

修改检查约束表达式

不允许修改 CHECK 限制条件的表达式,而是需要删除现有限制条件,并使用新表达式创建新限制条件。

查看检查限制条件的属性

Spanner 的 INFORMATION_SCHEMA 包含有关该检查的信息 数据库限制以下示例介绍了您可以通过查询信息架构回答的一些问题。

我的数据库中定义了哪些检查限制条件?

SELECT tc.CONSTRAINT_NAME, tc.TABLE_NAME, tc.CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
WHERE tc.CONSTRAINT_TYPE = 'CHECK';

数据库中的检查限制条件的当前状态如何?

如果向现有表添加了检查限制条件,则您可能需要查看当前状态,以确定(例如)是否已通过现有数据验证了所有现有数据。如果 SPANNER_STATE 返回 VALIDATING_DATA,则表示 Spanner 仍在根据该限制条件验证现有数据。

SELECT cc.CONSTRAINT_NAME, cc.SPANNER_STATE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS as cc;

后续步骤