如何防止在表格中删除第一行(PostgreSQL)?

13

如何在PostgreSQL中防止删除表的第一行?

我有一个类别表,并且希望防止默认类别被删除,因为这可能会破坏应用程序。当然,我可以轻松地在应用程序代码中实现它,但最好在数据库中实现。

我认为这与删除语句上的规则有关,但我在文档中找不到任何与我的问题相关的内容。

5个回答

24

你对规则系统的想法是正确的。 这里 有一个链接,其中包含一个与你的问题匹配的示例。 它甚至比触发器还要简单:

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;

一些答案忽略了一个要点:还必须限制对受保护行的更新。否则,可以首先更新受保护的行,使其不再满足禁止删除的条件,然后可以删除已更新的行,因为它不再受保护。


3
不确定为什么这个答案没有得到更多的赞,但保护规则真的很棒!:+1: - Dan Bradbury

15
你想在表上定义一个 BEFORE DELETE 触发器。当你尝试删除行(通过PK匹配或有单独的“保护”布尔列)时,RAISE一个异常。
我不熟悉PostgreSQL语法,但看起来是这样做的:
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();

谢谢您的回答。您和Macalendas都给出了有用的答案,让我很难选择“被采纳”的答案,但我决定把它交给Macalendas,以鼓励新用户参与这个令人惊叹的网站。谢谢! - Maiku Mori
没问题,很高兴能帮忙。我还刚刚在一个<a>标签中关闭了不匹配的引号,所以链接现在应该正常工作了。 - lc.
你需要在函数“RETURN OLD;”中添加。说明:请注意,在DELETE触发器中,NEW为null,因此返回它通常是不明智的。DELETE触发器中的惯用语是返回OLD。PostgreSQL文档 - Maxim Mandrik

5
我认为最好的方法是在该表上创建一个删除触发器。基本上,您需要编写一个存储过程来确保这个“默认”类别始终存在,并使用触发器ON DELETE事件来强制执行它。一个好的方法是创建一个按行触发器,可以保证在DELETE事件中,“默认”类别行永远不会被删除。

请查看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

3

你可以在另一个表格(称为 defaults)中拥有一行引用默认类别的数据。外键约束将阻止删除默认类别。


0

请记住触发器的工作原理。它们将为您的删除语句删除的每一行触发。这并不意味着您不应该使用触发器,只是要记住这一点,最重要的是测试您的使用场景,并确保性能符合要求。

我应该使用规则还是触发器?

根据官方文档: “对于两者都可以实现的事情,哪个更好取决于数据库的使用情况。触发器会为任何受影响的行触发一次。规则操作查询或生成额外的查询。因此,如果在一个语句中受影响的行很多,则发出一个额外命令的规则可能比为每个单独的行调用的触发器更快,并且必须执行其操作多次。但是,触发器方法在概念上比规则方法简单得多,并且更容易让新手正确使用。”

有关详细信息,请参见文档。
http://www.postgresql.org/docs/8.3/interactive/rules-triggers.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接