我有一个表格,我添加了一个布尔列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行被删除"并且不执行删除。
知道我的触发器有什么问题吗?
答案 0 :(得分:1)
这是因为要进行UPDATE,您需要返回NEW
记录。但是,要执行DELETE,您需要返回OLD
记录。
因此,如果触发函数希望触发操作在不改变行值的情况下正常成功,则必须返回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 $$;