如何防止批量删除行操作?

4
我可以像这样完全防止DELETE:

CREATE TRIGGER prevent_multiple_row_del
BEFORE DELETE ON ALL
BEGIN
RAISE EXCEPTION 'Cant delete more than 1 row at a time';
END;

但是如何检查删除操作是否会导致多行被删除?只要删除数量限制为常数(1、5或10,只要不是无限制),删除就不是问题。

另外,如何允许删除但防止完整表格被删除?


1
你确定你在使用Postgres吗?raise_application_error是Oracle PL/SQL过程。 - user330315
@a_horse_with_no_name 很抱歉,但是是的,我正在使用psql。我写了那段代码作为一个例子。 - player87
1个回答

3
一个before语句触发器太早了,无法知道受影响的行数。
对于整个表删除,使用一个after语句触发器。你只需要从表中选择并查看是否还有记录。
对于最多n条记录的删除,这也必须在after语句之后确定。你标记了你的问题是PostgreSQL,但正如a_horse_with_no_name指出的,你的代码是Oracle。在PostgreSQL中,你需要检查pg_affected_rows(),在Oracle中,你需要检查SQL%ROWCOUNT。我不知道PostgreSQL是否允许在after语句触发器中检查pg_affected_rows()。对于Oracle,在after语句触发器中检查SQL%ROWCOUNT是不起作用的。这个变量检查得太早了。
因此,至少对于Oracle来说,诀窍是在before语句之前设置一些自定义计数器为零,在每行之后增加,并在after语句之后检查。我不知道如何在PostgreSQL中精确地做到这一点,但肯定会有方法。在Oracle中,你会使用复合触发器,即包含单个触发器的超级触发器。
CREATE OR REPLACE TRIGGER prevent_multiple_row_del
FOR DELETE ON mytable COMPOUND TRIGGER
  v_count INTEGER := 0;

  AFTER EACH ROW IS
  BEGIN
    v_count := v_count + 1;
  END AFTER EACH ROW;

  AFTER STATEMENT IS
  BEGIN
    IF v_count > 1 THEN
      raise_application_error(-20000, 'Can''t delete more than 1 row at a time');
    END IF;
  END AFTER STATEMENT;

END prevent_multiple_row_del;

抱歉,是的,我正在使用psql,我只是写了那段代码作为示例。 - player87

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