是否可以防止在PostgreSQL端刪除表中的第一行?如何防止刪除表(PostgreSQL)中的第一行?
我有一個類別表,我想防止刪除默認類別,因爲它可能會中斷應用程序。當然,我可以很容易地在應用程序代碼中完成它,但是在數據庫中執行它會更好。
我認爲它與刪除語句上的規則有關,但我無法在文檔中找到任何與我的問題相近的東西。
是否可以防止在PostgreSQL端刪除表中的第一行?如何防止刪除表(PostgreSQL)中的第一行?
我有一個類別表,我想防止刪除默認類別,因爲它可能會中斷應用程序。當然,我可以很容易地在應用程序代碼中完成它,但是在數據庫中執行它會更好。
我認爲它與刪除語句上的規則有關,但我無法在文檔中找到任何與我的問題相近的東西。
我看到來完成,這是通過創建該表中刪除觸發器的最好方法。基本上,你必須編寫一個存儲過程來確保這個「默認」類別總是存在,然後在這個表上使用觸發器ON DELETE事件來強制執行它。一個很好的方法是創建一個每行觸發器,以保證在DELETE事件中'default'分類行永遠不會被刪除。
請看看PostgreSQL的有關觸發器的文件和存儲過程:
http://www.postgresql.org/docs/8.3/interactive/trigger-definition.html
http://www.postgresql.org/docs/8.3/interactive/plpgsql.html
還有在這個wiki有價值的例子:
http://wiki.postgresql.org/wiki/A_Brief_Real-world_Trigger_Example
你想在表上定義一個BEFORE DELETE trigger。當您嘗試刪除該行(或者由PK匹配或者有一個單獨的「保護」布爾列)時,RAISE是一個例外。
我不熟悉的PostgreSQL語法,但it looks like這是你會怎麼做:
CREATE FUNCTION check_del_cat() RETURNS trigger AS $check_del_cat$
BEGIN
IF OLD.ID = 1 /*substitute primary key value for your row*/ THEN
RAISE EXCEPTION 'cannot delete default category';
END IF;
END;
$check_del_cat$ LANGUAGE plpgsql;
CREATE TRIGGER check_del_cat BEFORE DELETE ON categories /*table name*/
FOR EACH ROW EXECUTE PROCEDURE check_del_cat();
你可以有一個在另一個表中的行(稱爲默認值)re預設默認類別。 FK約束不會讓刪除默認類別發生。
對於規則體系的思考你是對的。 Here是指向與您的問題匹配的示例的鏈接。它比觸發更簡單:
create rule protect_first_entry_update as
on update to your_table
where old.id = your_id
do instead nothing;
create rule protect_first_entry_delete as
on delete to your_table
where old.id = your_id
do instead nothing;
有些答案會錯過一個點:也是保護行的更新必須受到限制。否則,可以先更新受保護的行,使其不再滿足禁止刪除條件,然後可以刪除更新的行,因爲它不再受保護。
請記住觸發器是如何工作的。他們將刪除您的刪除語句將刪除的每一行。這並不意味着你不應該使用觸發器,只要記住這一點,最重要的是測試你的使用場景,並確保性能符合要求。
我應該使用規則還是觸發器?
從官方文檔: 「對於一種是可以被實現的東西,這是最好取決於數據庫的使用觸發器觸發任何受影響的行一次規則修改查詢或產生。所以如果在一個語句中有很多行受到影響,那麼發出一個額外命令的規則可能比爲每一行調用的觸發器要快,並且必須多次執行其操作。然而,觸發的方法是概念遠比規則的方法簡單,更容易爲初學者得到正確的。」
請參閱該文檔的詳細信息。
http://www.postgresql.org/docs/8.3/interactive/rules-triggers.html
感謝您的回答。你和Macalendas給所以很難選擇「接受」的答案,但我決定把它給予Macalendas,鼓勵新用戶參與這個驚人的網站。謝謝! – 2009-05-01 11:39:04
沒問題,很高興我可以幫忙。我也剛剛關閉了不匹配引用標記,以便鏈接現在可以正常工作 – 2009-05-01 12:08:50