每当某些其他表被更新时,我想用最新的时间戳更新master_table_info
表中的一行。表中的每一行对应于另一个表。我已经创建了此函数,但是无法将TG_TABLE_NAME
解释为变量值而不是新列。因此,我得到了错误column some_table does not exist
。如何将其解释为值?
CREATE OR REPLACE FUNCTION master_table_timestamp()
RETURNS TRIGGER AS
$$
BEGIN
EXECUTE format('
UPDATE master_table_info
SET updated_at = NOW()
WHERE table_name = %I', TG_TABLE_NAME);
RETURN NULL;
END;
$$
language plpgsql;
CREATE TRIGGER master_table_timestamp
BEFORE UPDATE ON some_table
EXECUTE PROCEDURE master_table_timestamp();
编辑
基于到目前为止的答案/评论并阅读了触发器文档,我意识到我应该使用TG_TABLE_NAME
并更改为AFTER
触发器。但是,使用触发器修改表不会对master_table_info
造成任何更改。怎么了?
CREATE OR REPLACE FUNCTION master_table_timestamp()
RETURNS TRIGGER AS
$$
BEGIN
UPDATE master_table_info
SET updated_at = NOW()
WHERE table_name = TG_TABLE_NAME;
RETURN new;
END;
$$
language plpgsql;
CREATE TRIGGER master_table_timestamp
AFTER UPDATE ON some_table
EXECUTE PROCEDURE master_table_timestamp();
第二次编辑
此代码在我上面的编辑中(基于答案的帮助)是正确的。我只需要强制手动刷新表即可正确显示它。
答案 0 :(得分:2)
%I
将占位符替换为标识符。因此,生成的SQL将是
UPDATE master_table_info
SET updated_at = NOW()
WHERE table_name = some_table;
要替换文字值,您需要%L
作为String中的占位符。 %L
占位符负责正确引用值,因此,如果使用该值,则生成的字符串将是:
UPDATE master_table_info
SET updated_at = NOW()
WHERE table_name = 'some_table';
这是您期望的。
但是,不需要动态SQL。在before
触发器中使用该函数时,重要的是从该函数返回一个非null值,否则UPDATE语句将被取消。
CREATE OR REPLACE FUNCTION master_table_timestamp()
RETURNS TRIGGER AS
$$
BEGIN
UPDATE master_table_info
SET updated_at = NOW()
WHERE table_name = TG_TABLE_NAME;
RETURN new; --<< return a NON-NULL value here!
END;
$$
language plpgsql;