Postgresql

何時檢查 IMMEDIATE 約束以及 Postgres 中的“語句”到底是什麼?

  • July 13, 2022

我目前對立即約束檢查的確切時間感到困惑。希望以下範例能解決我的困惑:

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;

在第二個查詢中,儘管引用了 t1,但expensive_exception_thrower將首先拋出其異常,這導致 fkey 異常被吞噬。當然,有一些解決方法,但是當 Postgres 手冊說在每個語句之後立即檢查 IMMEDIATE 約束時,我想了解“語句”的確切定義。手冊使用術語“語句”的方式表明 with 子句是一個語句,或者至少是“子語句”。

這是 PG 版本 14.3。

如評論中所述,語句是前一個語句終止符(通常是分號)和下一個語句終止符之間的所有內容,因此這是一個語句:

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

處理是這樣的:

  1. 插入東西。如果違反了主鍵、唯一性或檢查約束,則退出。
  2. 掃描returning結果集。
  3. 對每一行執行一個函式。如果拋出異常就退出。
  4. 到達結果集的末尾。
  5. 如果immediate違反了參照完整性約束,則退出。
  6. 一直持續到交易結束。
  7. 如果違反了deferred參照完整性約束,則退出。
  8. 犯罪。

引用自:https://dba.stackexchange.com/questions/314340