如何在PostgreSQL中防止删除表的第一行?
我有一个类别表,并且希望防止默认类别被删除,因为这可能会破坏应用程序。当然,我可以轻松地在应用程序代码中实现它,但最好在数据库中实现。
我认为这与删除语句上的规则有关,但我在文档中找不到任何与我的问题相关的内容。
如何在PostgreSQL中防止删除表的第一行?
我有一个类别表,并且希望防止默认类别被删除,因为这可能会破坏应用程序。当然,我可以轻松地在应用程序代码中实现它,但最好在数据库中实现。
我认为这与删除语句上的规则有关,但我在文档中找不到任何与我的问题相关的内容。
你对规则系统的想法是正确的。 这里 有一个链接,其中包含一个与你的问题匹配的示例。 它甚至比触发器还要简单:
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;
一些答案忽略了一个要点:还必须限制对受保护行的更新。否则,可以首先更新受保护的行,使其不再满足禁止删除的条件,然后可以删除已更新的行,因为它不再受保护。
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();
你可以在另一个表格(称为 defaults)中拥有一行引用默认类别的数据。外键约束将阻止删除默认类别。
请记住触发器的工作原理。它们将为您的删除语句删除的每一行触发。这并不意味着您不应该使用触发器,只是要记住这一点,最重要的是测试您的使用场景,并确保性能符合要求。
我应该使用规则还是触发器?
根据官方文档: “对于两者都可以实现的事情,哪个更好取决于数据库的使用情况。触发器会为任何受影响的行触发一次。规则操作查询或生成额外的查询。因此,如果在一个语句中受影响的行很多,则发出一个额外命令的规则可能比为每个单独的行调用的触发器更快,并且必须执行其操作多次。但是,触发器方法在概念上比规则方法简单得多,并且更容易让新手正确使用。”
有关详细信息,请参见文档。
http://www.postgresql.org/docs/8.3/interactive/rules-triggers.html