标准delete from foo_history where id = 123;
返回文字:
DELETE 1
我创建了一个触发程序来替换删除触发器,而不是删除,设置一个存档标志:
CREATE FUNCTION archive()
RETURNS trigger AS $$
DECLARE
command text := '" SET timeEnd = current_timestamp WHERE id = $1';
BEGIN
EXECUTE 'UPDATE "' || TG_TABLE_NAME || command USING OLD.id;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
然后为名为foo_history
的{{1}}表创建了一个视图:
foo
并在视图中添加了一个触发器:
CREATE VIEW foo AS
SELECT id, timeStart from foo_history WHERE timeEnd IS NULL;
换句话说,在删除CREATE TRIGGER foo_archive INSTEAD OF DELETE ON foo FOR EACH ROW EXECUTE PROCEDURE archive();
记录时,请改为设置foo
列 - 这样,timeEnd
视图仅显示未设置foo
的记录。
这很有效:
timeEnd
确实设置了delete from foo where id = 123
列。但是,这个输出是:
timeEnd
我真的想要它说:
DELETE 0
作为SQL新手和Postgres新手我不知道如何更改存档功能来执行此操作。
我确实尝试将其更改为:
DELETE 1
但是我得到一个错误,我需要返回一个复合材料(无论这意味着什么)。
答案 0 :(得分:2)
您已经发现RETURN OLD
触发器需要 INSTEAD OF
进行DELETE
操作才能使行计数在返回的命令标记中。手册:
行级
INSTEAD OF
触发器应返回NULL
以指示 它没有修改视图底层的任何数据 表,或者它应该返回传入的视图行(NEW
INSERT
和UPDATE
操作的行,或OLD
的DELETE
行 操作强>)。非空返回值用于表示触发器 在视图中执行必要的数据修改。 这会 导致受命令影响的行数增加。
大胆强调我的。
但是你当前的触发器中还有一个偷偷摸摸的 SQL注入错误。 TG_TABLE_NAME
是一个裸露的,不带引号的名称。标识符必须被视为用户输入 - 并且必须在必要时引用。在动态SQL语句中正确引用表名(或者您可能会受到影响)。一种方法是使用format()
:
CREATE OR REPLACE FUNCTION archive()
RETURNS trigger AS
$func$
BEGIN
EXECUTE format('UPDATE %I SET time_end = current_timestamp WHERE id = $1', TG_TABLE_NAME)
USING OLD.id;
RETURN OLD;
END
$func$ LANGUAGE plpgsql;
相关:
我还使用time_end
代替timeEnd
,因为我的常设建议是避免在Postgres中使用CaMeL案例标识符。相关:
答案 1 :(得分:0)
当然,我发布的第二篇文章,我有一个看似有用的想法..
而不是RETURN NULL
,请使用RETURN OLD