在 NOVALIDATE 方式下创建外键约束

ALTER TABLE ADD CONSTRAINT 语句可以创建或过滤 NOVALIDATE 方式的外键约束。NOVALIDATE 约束方式防止数据库服务器在创建引用约束时,验证每一行的外键值是否符合被引用表中的主键值。

使用此语法创建启用或过滤 NOVALIDATE 方式的外键约束:

ALTER TABLE ADD CONSTRAINT

元素 描述 限制 语法
constraint 发布此处约束的名称 在数据库中的索引和约束的名称中必须唯一 标识符
fk_col constraint 的外键列 必须存在于子表 标识符
pk_col 被引用表中的外键列 必须存在于被引用表 标识符
pk_tab 被引用表的名称 必须存在于当前数据库 标识符
table, synonym 放置 constraint 的表 必须存在于当前数据库 标识符

用法

该语法忽略 DISABLED 关键字。因为禁用的约束不会进行违例检查,在这种情况下,NOVALIDATE 关键字不重要。

如果没有列或列表立即跟随在 REFERENCES 关键字之后,则缺省列(或列组)是 pk_tab 表的主键。如果 pk_tabtablesynonym 指定同一表,则约束自我引用,并没有缺省的主键列。

如果您没有声明约束的名称,则数据库服务器为此新约束生成一个标识符,它注册在 sysconstraintssysobjstate 系统目录表中。

ALTER TABLE ADD CONSTRAINT 语句支持引用约束的 NOVALIDATE 方式作为创建或过滤引用约束时绕过数据完整性检查的机制。

NOVALIDATE 方式可以提高性能的情况

尽管引用约束保护数据完整性,在某些情况下您正要移动到新数据库服务器实例的数据库表是已知的自由参照完整性违规。对于大表上的外键约束,验证约束所需的时间要十分充分。如果有数百万行的表正从 OLTP 环境移动至数据仓库环境,则验证目标环境中的外键可能增加数量级迁移所需的时间。

例如,您可以删除大表上的外键约束,然后在该表迁移到目标表环境之前,立即重新创建 ENABLED NOVALIDATE 方式或 FILTERING NOVALIDATE 方式的约束。重建外键约束的 ALTER TABLE ADD CONSTRAINT 操作的花销几乎很小,因为它绕过了对每一行引用约束的验证。因为 NOVALIDATE 方式不会持续超过创建该约束的 ALTER TABLE 操作,抵达数据仓库环境中的表带有 ENABLED 或 FILTERING 方式的约束,保护了随后 DML 操作中数据的参照完整性。

使用 NOVALIDATE 关键字的限制

创建外键约束时, NOVALIDATE 关键字仅在 ALTER TABLE ADD CONSTRAINT 语句的 DDL 上下文中有效。 例如,您不能在以下任何 SQL 语句中创建处于 NOVALIDATE 方式的外键约束:
  • CREATE TABLE 语句
  • CREATE TEMP TABLE 语句
  • SELECT INTO TABLE 语句
如果满足下列条件,则您可以使用 ALTER TABLE ADD CONSTRAINT 语句在现有表上创建处于 NOVALIDATE 方式的启用约束:
  • 您正在添加的约束是外键约束。如果您在同一 ALTER TABLE 语句中创建多个约束,那么所有的约束必须都是外键约束。
  • 在 ALTER TABLE 语句中,NOVALIDATE 关键字只在 ADD CONSTRAINT FOREIGN KEY 选项中有效。
  • ALTER TABLE 在 DISABLED 方式下创建的约束是无效的。
如果在以下约束定义的语法上下文中包含 NOVALIDATE 关键字,则 ALTER TABLE 语句发生错误而失败:
  • ALTER TABLE ADD COLUMN 语句
  • ALTER TABLE INIT 语句
  • ALTER TABLE MODIFY 语句
使 NOVALIDATE 关键字有效的其它 DDL 语句只有 SET Database Object Mode 语句的 SET CONSTRAINTS 选项。当运行 SET CONSTRAINTS 语句时,它可以将现有外键约束的方式更改为这些 NOVALIDATE 约束方式:
  • ENABLED NOVALIDATE 方式
  • FILTERING WITH ERROR NOVALIDATE 方式
  • FILTERING WITHOUT ERROR NOVALIDATE 方式.
有关更多信息,请参阅 SET CONSTRAINTS 语句。

建立 NOVALIDATE 方式作为缺省方式

如果约束方式规范忽略 NOVALIDATE 关键字,则 SQL 的 SET ENVIRONMENT NOVALIDATE ON 语句和加载数据库的 dbimport -nv 命令都可以重写任何由 ALTER TABLE ADD CONSTRAINT 或 SET CONSTRAINTS 语句指定的外键约束方式(除了 DISABLED)。
  • SET ENVIRONMENT NOVALIDATE ON 语句的范围是同一用户会话中 ALTER TABLE ADD CONSTRAINT 和 SET CONSTRAINTS 语句的后续。
  • dbimport -nv 命令的范围是导出数据库的 .sql 文件中的 ALTER TABLE ADD CONSTRAINT 和 SET CONSTRAINTS 语句,其路径名在同一 dbimport 命令中指定。

创建 NOVALIDATE 方式的约束的示例

以下 DDL 语句创建了名为 parent 的表且在该表的 c1 列上定义了唯一索引和主键约束:
CREATE TABLE parent(c1 INT, c2 INT, c3 INT);
          CREATE UNIQUE INDEX idx_parent_c1 ON parent(c1);
          ALTER TABLE parent ADD CONSTRAINT 
          PRIMARY KEY(c1) CONSTRAINT cons_parent_c1;

以下语句创建了另一个表,名为 child,它的第一列与 parent 表的主键列的数据类型相同,并在 child 表定义主键约束 cons_child_x

CREATE TABLE child(x1 INT, x2 INT, x3 VARCHAR(32));
        ALTER TABLE child 
        ADD CONSTRAINT (FOREIGN KEY(x1) 
        REFERENCES parent(c1) CONSTRAINT cons_child_x1);
      

假设之后的 DML 操作(未显示)向此 parent 表和 child 表填充数据行。在一些点,此工作流程要求数据从它的 OLTP 产品环境移动到另一个处理业务分析应用程序的数据库中。

如果在这一点,child 表中的数据集包含大量行,则验证 cons_child_x1 引用约束将会是新数据库导入 child 表要花费的显著成本。以下语句删除此约束:
ALTER TABLE child DROP CONSTRAINT cons_child_x1;
child 表导入到新的环境后,下列语句可以在 child 表上重建一个相同名称的约束,而不用检查每一行的参照完整性违规:
ALTER TABLE child
          ADD CONSTRAINT (FOREIGN KEY(x1)
          REFERENCES parent(c1)
          CONSTRAINT cons_child_x1 NOVALIDATE);
ALTER TABLE 语句执行完毕之后,新的 cons_child_x1 引用约束在缺省情况下处于 ENABLED 方式。
1 请参阅 过滤模式
2 只对 FOREIGN KEY 约束有效