当您定义外键约束时包含可选的 INDEX DISABLED 关键字,可以放置表上的 DML 操作使用与数据库服务器关联的外键的索引。如果您包含 INDEX DISABLED 关键字,则它们必须是 ALTER TABLE 语句的最后规范。
要添加外键约束,您必须在被引用列或子表上拥有 References 权限。如果您拥有父表或有对父表的 Alter 权限,则您可以在该表上创建外键约束并指定您子句作为此约束的所有者。当您持有 DBA 权限时,您可以为其他用户创建外键约束。
当 ALTER TABLE ADD CONSTRAINT 语句在引用子表的一列或一组列上放置外键约束,且该列或该组列没有引用约束或用户定义索引存在时,数据库服务器在指定的列或列组上创建一个内部 B-tree 索引。如果用户定义索引已经存在,则约束共享现有的索引。
如果 ALTER TABLE ADD CONSTRAINT 语句在同一表上定义多个外键,则每个约束需要它自己的 REFERENCES 子句,并为每个约束指定(或忽略)INDEX DISABLED 关键字。
INDEX DISABLED 选项在从集群环境中更新辅助服务器语句中发出的 ALTER TABLE ADD CONSTRAINT 语句中有效。
尽管引用约束保护数据完整性,在某些情况下用户定义或系统生成的与数据库服务器关联的外键约束的 B-tree 索引可以降低表(表很大)的操纵数据操作的效率。如果未从父表删除,则该索引不用在子表中锁定行以级联删除。如果子表不需要使用此索引进行查询。在此情境中,并不需要索引,但是这并不意味在子表中修改、删除和插入行的操作中该索引是不重要的。如果禁用对应于外键约束的索引,则在子表上存取数百万行数据的应用可能需要较少的资源。
在这些情况下,ALTER TABLE ADD CONSTRAINT 语句的 INDEX DISABLED 关键字选项提供一个机制,即定义外键时避免大量关联 b-tree 索引的开销。
当您在约束定义的末尾包含 INDEX DISABLED 关键字时,如果没有合适的用户定义索引存在,数据库服务器禁用系统生成的索引。如果在子表上的外键列或(列组)已存在用户定义索引,则数据库服务器禁用该索引。随后的子表上的 DML 存在会在没有索引的情况下实现,而且只需要最小的系统资源以维护和存储该禁用的索引。
当您在约束定义的末尾包含 INDEX DISABLED 关键字时,如果没有合适的用户定义索引存在,则数据库服务器禁用系统生成的索引。如果在子表上的外键列或(列组)已存在用户定义索引,则数据库服务器禁用该索引。随后的子表上的 DML 存在会在没有索引的情况下实现,而且只需要最小的系统资源以维护和存储该禁用的索引。
INDEX DISABLED 关键字对于您定义的外键约束没有影响。数据库服务器强制执行此约束,如果随后对子表或父表的 DML 操作违例了指定外键约束则发出错误。
ALTER TABLE child ADD CONSTRAINT(FOREIGN KEY(x1) REFERENCES parent(c1) CONSTRAINT cons_child_x1 DISABLED INDEX DISABLED);
要纠正以上 ALTER TABLE ADD CONSTRAINT 示例中的错误,您必须删除第一个 DISABLED 关键字,或者删除 INDEX DISABLED 关键字。
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; CREATE TABLE child(x1 INT, x2 INT, x3 VARCHAR(32)); CREATE INDEX idx_child_x1 ON child(x1); ALTER TABLE child ADD CONSTRAINT(FOREIGN KEY(x1) REFERENCES parent(c1) CONSTRAINT cons_child_x1 INDEX DISABLED);
然而,对于某些含有主键和外键依赖的表,查询优化器可能会在执行计划中选择基于 WHERE 子句子表上的其它索引。
如上所述,在外键定义中使用 INDEX DISABLED 选项只有在子表非常大时才可能提高性能,通常在数据仓库应用的情况下。不建议在小的表上使用该语法选项操作。