在PostgreSQL中禁用表的DELETE操作?

28

为了安全敏感的设计,我想禁止在某些表上执行DELETE操作。

DELETE操作只应在行上设置一个deleted标记(该标记将在视图上可见,并由应用程序层使用)。

据我所知,规则会生成额外的查询语句,因此规则不能抑制原始查询。

以下是一个玩具示例,使用触发器(尚未测试):

-- data in this table should be 'undeletable'
CREATE table article (
    id serial,
    content text not null,
    deleted boolean default false
)

-- some view that would only show articles, that are NOT deleted
...

-- toy trigger (not tested)
CREATE OR REPLACE FUNCTION suppress_article_delete()
RETURNS TRIGGER AS $sad$
BEGIN
    IF (TG_OP = 'DELETE') THEN
        UPDATE article SELECT id, content, TRUE;
        -- NEW or NULL??
        RETURN NEW;
    END IF;
    RETURN NULL;
END;
$sad$ LANGUAGE plpgsql;

如何有效地禁用 DELETE 操作?

1个回答

39

据我理解,规则会生成额外的查询 - 因此规则无法抑制原始查询。

不完全正确 - 它可以是一个INSTEAD覆盖规则:

 CREATE RULE shoe_del_protect AS ON DELETE TO shoe DO INSTEAD NOTHING;

(该手册同一页中的示例)。

另一种方法是在相关表上REVOKE删除权限,并创建用于删除、更新和插入的存储过程。


谢谢!我想把这个“undelete”设计放到数据模型中,而不是管理(撤销)-所以我猜我会尝试一个INSTEAD规则。 - miku
5
ON DELETE DO INSTEAD NOTHING 的问题在于,执行 DELETE 操作的代码不会收到“什么都没发生”的通知——对于客户端而言,DELETE 操作成功了,但潜在的错误却被忽略了。为此,可能会出现一些隐蔽性的错误。 - peschü
3
@peschü 确实。避免该问题的一种方法是:`create or replace function raiseException() returns void language plpgsql volatile as $$ begin raise exception '无法删除行。'; end$$;CREATE or replace RULE prevent_deletes AS ON DELETE TO shoe DO INSTEAD select raiseException(); ` - Elifarley

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