阻止任何更新或从表中删除

时间:2016-09-22 10:56:23

标签: sql postgresql

我有一个表格,我添加了一个布尔列done 当此列为True时,我想阻止对该行进行任何未受管理的操作(删除,更新)。

我写了这个触发器:

CREATE TRIGGER productstock_beforeupdate
  BEFORE UPDATE OR DELETE
  ON table
  FOR EACH ROW
  EXECUTE PROCEDURE trig()

CREATE OR REPLACE FUNCTION trig()
  RETURNS trigger AS
$$
begin
    if TG_OP='UPDATE' or TG_OP='DELETE' then
        if old.done=true then
                    raise exception 'cant do that';
            return null;
        end if;
    end if;
    return new;
end;
$$

如果autorized事务想要更改数据,它将首先禁用此触发器。

当我尝试用

删除行时,这个想法应该有效
done=False

它返回我" 0行被删除"并且不执行删除。

知道我的触发器有什么问题吗?

2 个答案:

答案 0 :(得分:1)

这是因为要进行UPDATE,您需要返回NEW记录。但是,要执行DELETE,您需要返回OLD记录。

Quote from the manual

  

因此,如果触发函数希望触发操作在不改变行值的情况下正常成功,则必须返回NEW(或与其相等的值)[...]注意,在DELETE触发器中NEW为空,因此返回这通常是不明智的。 DELETE触发器中通常的习惯用法是返回OLD。

所以你的触发器功能应如下所示:

CREATE OR REPLACE FUNCTION trig()
  RETURNS trigger AS
$$
begin
  -- no need to check for the action here as the trigger
  -- will only fire for UPDATE or DELETE
  if old.done then
    raise exception 'cant do that';
    return null;
  end if;

  if TG_OP='UPDATE' then 
    return new;
  end if; 

  if TG_OP='DELETE' then
    return old;
  end if;
end;
$$
language plpgsql;

答案 1 :(得分:1)

当触发器允许DELETE时,它应返回old。如果UPDATE,则返回new。 如果它引发异常,则不需要返回任何内容。

create or replace function trig()
  returns trigger language plpgsql as
$$
begin
    if old.done then
        raise exception 'cant do that';
    end if;
    if tg_op = 'DELETE' then
        return old;
    else
        return new;
    end if;
end $$;