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

时间:2009-05-01 04:21:37

标签: sql postgresql rules

是否可以防止在PostgreSQL端删除表中的第一行?

我有一个类别表,我想阻止删除默认类别,因为它可能会破坏应用程序。当然,我可以在应用程序代码中轻松完成它,但在数据库中执行它会好得多。

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

5 个答案:

答案 0 :(得分:11)

你想到规则系统是对的。 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;

有些答案错过了一点:还必须限制受保护行的更新。否则,可以先更新受保护的行,使其不再满足禁止删除标准,然后可以删除更新的行,因为它不再受保护。

答案 1 :(得分:10)

您想在桌面上定义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();

答案 2 :(得分: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 :(得分:1)

您可以在另一个表(称为默认值)中引用默认类别的行。 FK约束不允许删除默认类别。

答案 4 :(得分:0)

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

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

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

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