不可延期与可初始化立即
我阅读了关于数据库系统 – 完整书中的SQL关键字DEFERRABLE
。
后者[NOT DEFERRABLE]是缺省值,意味着每次执行数据库修改语句时,如果修改可能违反外键约束,则会立即检查约束。
但是,如果我们声明约束为DEFERRABLE ,那么在检查约束之前,我们可以select等待事务完成。
我们按照INITIALLY DEFERRED或INITIALLY IMMEDIATE关键字DEFERRABLE 。 在前一种情况下,检查将延迟到每个事务提交之前。 在后一种情况下,支票将在每次发言后立即进行。
NOT DEFERRABLE
与DEFERRABLE INITIALLY IMMEDIATE
什么不同? 在这两种情况下,似乎在每个单独的陈述之后检查任何约束。
通过可延迟DEFERRABLE INITIALLY IMMEDIATE
您可以在需要时延迟需求约束。
如果您通常希望在语句时间检查约束,那么这非常有用,但是例如批处理负载想要在提交时间之前推迟检查。
不过,各种DBMS的约束语法是不同的。
使用NOT DEFERRABLE
您将永远无法推迟检查,直到提交时间。
除了显而易见的延迟之外,差异实际上是performance。 如果没有performance惩罚,那么就没有必要有select延迟的选项 – 所有的限制都是可以推迟的。
性能损失与数据库可以执行的优化有关,只要知道如何限制数据。 例如,如果约束是可延迟的,因为临时允许重复,则在Oracle中创build的用于支持唯一约束的索引不能是唯一索引。 但是,如果约束不可推迟,那么索引可以是唯一的。
除了其他(正确的)答案之外,还必须说明:
-
用NOT DEFERRABLE在插入/更新时检查每一行
-
与DEFERRABLE (当前IMMEDIATE )在插入/更新结束时检查所有行
-
使用DEFERRABLE (当前为DEFERRED ),在事务结束时检查所有行
所以说当一个DEFERRABLE约束被设置为IMMEDIATE时,它的行为就像一个NOT DEFERRABLE约束是不正确的 。
让我们来详细说明这个区别:
CREATE TABLE example( row integer NOT NULL, col integer NOT NULL, UNIQUE (row, col) DEFERRABLE INITIALLY IMMEDIATE ); INSERT INTO example (row, col) VALUES (1,1),(2,2),(3,3); UPDATE example SET row = row + 1, col = col + 1; SELECT * FROM example;
这正确输出:
但是如果我们删除了DEFERRABLE INITIALLY IMMEDIATE指令,
错误:重复键值违反唯一约束“example_row_col_key”细节:键(“row”,col)=(2,2)已经存在。 **********错误**********
错误:重复键值违反唯一约束“example_row_col_key”SQL状态:23505详细信息:键(“row”,col)=(2,2)已经存在。
附录 (2017年10月12日)
这种行为确实logging在这里 ,“兼容性”部分:
另外,PostgreSQL会立即检查不可延迟的唯一性约束,而不是像标准所build议的那样在语句结束时检查。
NOT DEFERRABLE – 你不能改变约束检查,oracle在每个语句之后(即直接在insert语句之后)检查它。
直接初始化 – oracle在每个语句后检查约束。 但是,你可以改变它在每个事务之后(即提交之后):
set constraint pk_tab1 deferred;