簡體   English   中英

Postgres:忽略級聯刪除的 DELETE 觸發器

[英]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 以便您有一個不可為空的外鍵約束,從personsemail_addresses鏈接到人員的地址之一。 然后您的要求會自動滿足,您不需要觸發器。

這將使刪除電子郵件地址之類的事情變得更加復雜,但您不必依賴觸發器來確保完整性,因為完整性總是受制於競爭條件

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM