【问题标题】:How to prevent deletion of the first row in table (PostgreSQL)?如何防止删除表中的第一行(PostgreSQL)?
【发布时间】:2010-10-23 01:12:06
【问题描述】:

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

我有一个类别表,我想防止删除默认类别,因为它可能会破坏应用程序。当然,我可以很容易地在应用程序代码中做到这一点,但在数据库中做到这一点会好得多。

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

【问题讨论】:

    标签: sql postgresql rules


    【解决方案1】:

    您想在表上定义一个 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();
    

    【讨论】:

    • 感谢您的回答。您和 Macalendas 都给出了有用的答案,因此很难选择“接受”的答案,但我决定将其提供给 Macalendas,以鼓励新用户参与这个令人惊叹的网站。谢谢!
    • 您需要添加到函数RETURN OLD; 信息:注意NEW 在DELETE 触发器中为空,因此返回它通常是不明智的。 DELETE 触发器中的常用习惯用法是返回 OLD。 postgresql docs
    【解决方案2】:

    我认为完成此操作的最佳方法是在此表上创建删除触发器。基本上,您必须编写一个存储过程以确保此“默认”类别将始终存在,然后使用此表上的触发器 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】:

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

      【讨论】:

        【解决方案4】:

        你对规则系统的思考是对的。 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:
        【解决方案5】:

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

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

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

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

        【讨论】:

          猜你喜欢
          • 2015-12-25
          • 2020-10-05
          • 1970-01-01
          • 2023-04-10
          • 1970-01-01
          • 2014-01-30
          • 2015-07-10
          • 2021-12-07
          • 2019-10-12
          相关资源
          最近更新 更多