我DEFERRABLE
在数据库系统 - 完整的书中读到了关于SQL关键字的内容.
后者[NOT DEFERRABLE]是默认值,意味着每次执行数据库修改语句时,如果修改可能违反外键约束,则会立即检查约束.
但是,如果我们将约束声明为DEFERRABLE,那么我们可以选择让它等到事务完成后再检查约束.
我们按照关键字DEFERRABLE通过两种INITIALLY DEFERRED或者INITIALLY IMMEDIATE.在前一种情况下,检查将推迟到每个事务提交之前.在后一种情况下,将在每个陈述后立即进行检查.
有什么NOT DEFERRABLE
不同DEFERRABLE INITIALLY IMMEDIATE
?在这两种情况下,似乎在每个单独的陈述之后检查任何约束.
a_h*_*ame 63
有了DEFERRABLE INITIALLY IMMEDIATE
你可以推迟的约束需求,当你需要它.
如果您通常希望在语句时检查约束,但是例如批量加载要将检查推迟到提交时间,这将非常有用.
但是,对于各种DBMS,如何推迟约束的语法是不同的.
在NOT DEFERRABLE
您提交时间之前,您永远无法将检查推迟.
Tee*_*jay 31
除了其他(正确的)答案,在谈到PostgreSQL时,必须说明:
在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;
Run Code Online (Sandbox Code Playgroud)
这正确输出:
但是如果我们删除DEFERRABLE INITIALLY IMMEDIATE指令,
错误:重复键值违反唯一约束"example_row_col_key"DETAIL:键("row",col)=(2,2)已存在.**********错误**********
错误:重复键值违反唯一约束"example_row_col_key"SQL状态:23505详细信息:键("row",col)=(2,2)已存在.
附录 (2017年10月12日)
这种行为确实在此处记录,"兼容性"部分:
此外,PostgreSQL会立即检查不可延迟的唯一性约束,而不是像标准所暗示的那样在语句结束时检查.
Rya*_*yan 26
除了能够推迟的明显之外,差异实际上是表现.如果没有性能损失,那么就没有必要选择是否可以推迟 - 所有约束都只是可以推迟的.
在了解数据如何受限的情况下,性能损失与数据库可以执行的优化有关.例如,如果约束是可延迟的,那么为了支持Oracle中的唯一约束而创建的索引不能是唯一索引,因为必须允许临时允许重复.但是,如果约束不可延迟,则索引可以是唯一的.
我参加聚会已经很晚了,但我想补充一点——截至 2018 年 12 月——我所知道的只有两个数据库(可能还有更多)提供了这个标准 SQL 功能的某种程度的实现:
Database NOT DEFERRABLE DEFERRABLE DEFERRABLE
INITIALLY IMMEDIATE INITIALLY DEFERRED
---------- -------------- ------------------- ------------------
Oracle N/A *1 Yes (default) Yes
PostgreSQL Yes (default) Yes Yes
DB2 - - -
SQL Server - - -
MySQL - - -
MariaDB - - -
SAP Sybase - - -
HyperSQL - - -
H2 - - -
Derby - - -
Run Code Online (Sandbox Code Playgroud)
*1 尽管 Oracle 12c 接受NOT DEFERRABLE
约束状态,但它实际上会忽略它并使其像DEFERRABLE INITIALLY IMMEDIATE
.
如您所见,Oracle 没有实现第一种类型 ( NOT DEFERRABLE
),这就是使用 Oracle(在本例中为 OP)的开发人员可能会感到困惑并认为前两种类型等效的原因。
有趣的是,Oracle 和 PostgreSQL 有不同的默认类型。也许它有性能影响。
小智 5
NOT DEFERRABLE - 您不能更改约束检查,oracle 在每个语句之后(即直接在插入语句之后)对其进行检查。
DEFERRABLE INITIALLY IMMEDIATE - oracle 在每个语句之后检查约束。但是,您可以在每个事务之后(即提交之后)将其更改为:
set constraint pk_tab1 deferred;
Run Code Online (Sandbox Code Playgroud)