到底什么时候检查 IMMEDIATE 约束以及 Postgres 中的“语句”到底是什么?

use*_*071 4 postgresql constraint

我目前对立即约束检查的确切时间感到困惑。希望下面的例子能解决我的困惑:

create table a (
  id int primary key
);

create table b (
  id int primary key,
  a_id int not null references a
);

/* violates foreign key constraint "b_a_id_fkey" */
with t1 as (insert into b values (100, 200) returning id, a_id)
  select * from t1;

/* ERROR: expensive_exception_thrower */
with t1 as (insert into b values (100, 200) returning id, a_id)
  select * from t1 where expensive_exception_thrower(t1.a_id) = true;
Run Code Online (Sandbox Code Playgroud)

在第二个查询中,尽管引用了 t1,但expensive_exception_thrower仍会首先抛出其异常,这会导致 fkey 异常被吞没。当然,有解决方法,但是当 Postgres 手册说在每个语句之后立即检查 IMMEDIATE 约束时,我想了解“语句”的确切定义。本手册使用术语“语句”的方式表明 with 子句是一个语句,或者至少是“子语句”。

这是 PG 版本 14.3。

mus*_*cio 11

正如评论中提到的,语句是前一个语句终止符(通常是分号)和下一个语句之间的所有内容,所以这是一个语句:

with t1 as (insert into b values (100, 200) returning id, a_id)
  select * from t1 where expensive_exception_thrower(t1.a_id) = true;
Run Code Online (Sandbox Code Playgroud)

处理过程如下:

  1. 插入东西。如果违反主键、唯一或检查约束,则进行救助。
  2. 扫描returning结果集。
  3. 对于每一行执行一个函数。如果抛出异常则退出。
  4. 到达结果集的末尾。
  5. immediate如果违反引用完整性约束则退出。
  6. 继续直到交易结束。
  7. deferred如果违反引用完整性约束则退出。
  8. 犯罪。