不可延期与可初始化立即

我阅读了关于数据库系统 – 完整书中的SQL关键字DEFERRABLE

后者[NOT DEFERRABLE]是缺省值,意味着每次执行数据库修改语句时,如果修改可能违反外键约束,则会立即检查约束。

但是,如果我们声明约束为DEFERRABLE ,那么在检查约束之前,我们可以select等待事务完成。

我们按照INITIALLY DEFERREDINITIALLY IMMEDIATE关键字DEFERRABLE 。 在前一种情况下,检查将延迟到每个事务提交之前。 在后一种情况下,支票将在每次发言后立即进行。

NOT DEFERRABLEDEFERRABLE 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;