Postgresql

我可以在包含主鍵列的複合外鍵上使用“on delete set null”嗎?

  • August 4, 2015

文件說:

限制和級聯刪除是兩個最常見的選項。RESTRICT 防止刪除引用的行。NO ACTION 表示如果在檢查約束時仍然存在任何引用行,則會引發錯誤;如果您不指定任何內容,這是預設行為。(這兩種選擇之間的本質區別是 NO ACTION 允許將檢查推遲到事務的後期,而 RESTRICT 不允許。) CASCADE 指定當一個引用的行被刪除時,引用它的行應該被自動刪除也是。還有兩個其他選項:SET NULL 和 SET DEFAULT。當引用的行被刪除時,這些會導致引用行中的引用列分別設置為空值或其預設值. 請注意,這些並不能成為您遵守任何約束的藉口。例如,如果一個操作指定了 SET DEFAULT 但預設值不滿足外鍵約束,則操作將失敗。

但是沒有說明on delete set null如果只有一個外鍵列可以為空,或者它只是將可以為空的部分設置為空,是否會失敗,是什麼?

on delete set null如果任何外鍵列不接受,則不能使用null

create schema stack;
set search_path=stack;
--
create table t1( foo integer
              , bar integer
              , primary key(foo,bar) );
--
create table t2( foo integer
              , baz integer
              , bar integer
              , primary key (foo,baz)
              , foreign key (foo,bar) references t1 on delete set null );
--
insert into t1 values (1,1);
insert into t2 values (1,1,1);
delete from t1;
/*
ERROR:  null value in column "foo" violates not-null constraint
DETAIL:  Failing row contains (null, 1, null).
CONTEXT:  SQL statement "UPDATE ONLY "postgres"."t2" SET "foo" = NULL, "bar" = NULL WHERE $1 OPERATOR(pg_catalog.=) "foo" AND $2 OPERATOR(pg_catalog.=) "bar""
*/
--
drop schema stack cascade;

對於on delete set default. 我不知道有什麼簡單的方法可以解決這個問題,而且我不確定我是否同意這是最明智的行為,我認為更好的選擇是on delete set null將可空列設置為 null 如果兩者都有。

您將無法從引用表中刪除任何內容,因為鍵的一部分發生在其他鍵上(即:SET NULL、SET DEFAULT 等),如果需要設置 NULL 和其他保持原樣。

我遇到了同樣的問題,解決方法是在引用的表上設置一個 BEFORE DELETE 觸發器。

就我而言,我有: ORDERS (distributor_code, order_id PK)

SHIP_TO (distributor_code, order_id FK to ORDERS, invoice_id, address_data…)

SHIP_TO對distributor_code、invoice_id 上的INVOICES 進行FK,但invoice_id 可能為NULL。

如果我嘗試從 INVOICES 中刪除並且有連結,則會失敗。

INVOICES 上的 BEFORE DELETE 觸發器將 invoice_id 設置為 NULL,但在 (distributor_code, invoice_id) 匹配修復它的位置保留distributor_code 完整。

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