SET CONSTRAINTS — 设置当前事务的约束检查时机
SET CONSTRAINTS { ALL | name [, ...] } { DEFERRED | IMMEDIATE }
SET CONSTRAINTS 设置当前事务内约束检查的行为。IMMEDIATE 约束会在每条语句的末尾被检查。DEFERRED 约束则要到事务提交时才会被检查。每个约束都有它自己的 IMMEDIATE 或 DEFERRED 模式。
在创建时,约束会被赋予三种特性之一:DEFERRABLE INITIALLY DEFERRED、DEFERRABLE INITIALLY IMMEDIATE 或 NOT DEFERRABLE。第三类总是 IMMEDIATE 的,并且不受 SET CONSTRAINTS 命令的影响。前两类会以被指定的模式开始每一个事务,但它们的行为可以在事务内通过 SET CONSTRAINTS 改变。
带有一个约束名列表的 SET CONSTRAINTS 只会改变这些约束(它们必须都是可延迟的)的模式。每个约束名都可以用模式名限定。如果没有指定模式名,则使用当前的模式搜索路径来查找第一个匹配的名称。SET CONSTRAINTS ALL 会改变所有可延迟约束的模式。
当 SET CONSTRAINTS 把一个约束的模式从 DEFERRED 改为 IMMEDIATE 时,新模式会追溯生效:任何原本将在事务结束时被检查的未决数据修改,会在 SET CONSTRAINTS 命令执行期间被检查。如果违反了任何这样的约束,SET CONSTRAINTS 就会失败(并且不会改变约束模式)。因此,可以使用 SET CONSTRAINTS 来强制约束检查发生在一个事务中的特定时点。
目前,只有 UNIQUE、PRIMARY KEY、REFERENCES(外键)和 EXCLUDE 约束会受到该设置的影响。NOT NULL 和 CHECK 约束总是在行被插入或修改时立即被检查(而不是在语句末尾检查)。未声明为 DEFERRABLE 的唯一性约束和排他约束也会被立即检查。
被声明为“约束触发器”的触发器的触发也受该设置控制 — 它们会在相关联的约束本应被检查的同一时刻触发。
由于 PostgreSQL 不要求约束名在一个模式内唯一(只要求在一个表内唯一),指定的约束名可能会有不止一个匹配。在这种情况下,SET CONSTRAINTS 会作用于所有匹配。对于非模式限定的名称,一旦在搜索路径的某个模式中找到了一个或多个匹配,就不会再搜索路径中更靠后的模式。
该命令只改变当前事务内约束的行为。在事务块之外发出该命令会发出一条警告,此外没有任何效果。
该命令符合 SQL 标准中定义的行为,但有一个限制:在 PostgreSQL 中,它不适用于 NOT NULL 和 CHECK 约束。此外,PostgreSQL 会立即检查不可延迟的唯一性约束,而不是像标准所暗示的那样在语句末尾检查。