不可推迟与可推迟的初始即时相比

Pie*_*ter 78 sql database

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您提交时间之前,您永远无法将检查推迟.

  • @onedaywhen我的一位同事后来指出了一个很好的正当理由,实际上:你可以在任何交易的任何一点依赖不可延迟的约束,但只能在交易开始时观察到可推迟的约束. (4认同)

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中的唯一约束而创建的索引不能是唯一索引,因为必须允许临时允许重复.但是,如果约束不可延迟,则索引可以是唯一的.


The*_*ler 8

我参加聚会已经很晚了,但我想补充一点——截至 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)