[英]Postgres: Ignore DELETE triggers for cascade deletes
我正在嘗試實現人員與 email 地址的關系,其中一個人必須始終擁有至少一個 email 地址。 表格如下所示:
CREATE TABLE persons (
id serial PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE email_addresses (
id serial PRIMARY KEY,
person_id integer REFERENCES persons (id) ON DELETE CASCADE ON UPDATE CASCADE,
email_address text NOT NULL
);
為了實現一個人必須至少有一個 email 地址的約束,我想我會使用觸發器。 滿足約束所必需的觸發器之一是email_addresses
表上的BEFORE DELETE
觸發器,如果DELETE
將刪除一個人的最后一個 email 地址,則會引發錯誤:
CREATE FUNCTION email_addresses_delete_trigger() RETURNS trigger AS $$
DECLARE
num_email_addresses integer;
BEGIN
num_email_addresses := (SELECT count(*) FROM email_addresses WHERE person_id = OLD.person_id);
IF num_email_addresses < 2 THEN
RAISE EXCEPTION 'A person must have at least one email address';
END IF;
RETURN OLD;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER email_addresses_delete_trigger BEFORE DELETE ON email_addresses
FOR EACH ROW EXECUTE FUNCTION email_addresses_delete_trigger();
這個觸發器做了它應該做的事情,但是它阻止了從persons
表中刪除一個人。 例如:
mydb=# DELETE FROM persons WHERE id = 1;
ERROR: A person must have at least one email address
CONTEXT: PL/pgSQL function email_addresses_delete_trigger() line 7 at RAISE
SQL statement "DELETE FROM ONLY "public"."email_addresses" WHERE $1 OPERATOR(pg_catalog.=) "person_id""
如果我要刪除一個人,那么我也希望刪除他們所有的 email 地址,因此我不在乎在級聯刪除過程中是否保持觸發器表示的約束。 當一個人被刪除時,有沒有辦法“忽略”這個觸發器? 還是有其他方法我需要刪除一個人?
我的建議是更改數據 model 以便您有一個不可為空的外鍵約束,從persons
到email_addresses
鏈接到人員的地址之一。 然后您的要求會自動滿足,您不需要觸發器。
這將使刪除電子郵件地址之類的事情變得更加復雜,但您不必依賴觸發器來確保完整性,因為完整性總是受制於競爭條件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.