我正在使用PostgreSQL 9.2.23。 我有一个触发器函数,该函数具有多个在格式语句中重复使用相同标识符的语句。为了简洁起见,我只包含一个execute语句。
CREATE OR REPLACE FUNCTION update_lookup_table() RETURNS trigger AS
$BODY$
DECLARE
arg_key text;
arg_desc text;
arg_table text;
BEGIN
arg_key := TG_ARGV[0];
arg_desc := TG_ARGV[1];
arg_table := TG_ARGV[2];
EXECUTE format('DROP TABLE IF EXISTS %s',
quote_ident('temp_' || arg_table));
EXECUTE format('CREATE TEMPORARY TABLE %s(%I text, %I text)',
quote_ident('temp_' || arg_table), arg_key, arg_desc);
EXECUTE format('INSERT INTO %s(%I, %I)
SELECT DISTINCT %I, %I
from staging_staff',
quote_ident('temp_' || arg_table), arg_key, arg_desc,
arg_key, arg_desc);
EXECUTE format('LOCK TABLE %I IN EXCLUSIVE MODE',
arg_table);
EXECUTE format('UPDATE %I
SET %I = %s.%I
FROM %s
WHERE %s.%I = %I.%I',
arg_table,
arg_desc, quote_ident('temp_' || arg_table), arg_desc,
quote_ident('temp_' || arg_table),
quote_ident('temp_' || arg_table), arg_key, arg_table, arg_key);
EXECUTE format('INSERT INTO %I (%I, %I)
SELECT %s.%I, %s.%I
FROM %s
LEFT OUTER JOIN %I ON ( %I.%I = %s.%I )
WHERE %I.%I IS NULL',
arg_table, arg_key, arg_desc,
quote_ident('temp_' || arg_table), arg_key, quote_ident('temp_' || arg_table), arg_desc,
quote_ident('temp_' || arg_table),
arg_table, arg_table, arg_key, quote_ident('temp_' || arg_table), arg_key,
arg_table, arg_key);
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql;
以下是触发更多上下文的触发器:
CREATE Trigger trig_update_staff_code
AFTER INSERT OR UPDATE ON staging_staff
EXECUTE PROCEDURE update_lookup_table('staffgroupcode','staffgroupdescription','staff_group');
我正在使用的某些语句很长,并且最终变得很愚蠢,并且不断重复相同的3个标识符。 如您在格式声明中看到的,我重复使用了arg_key和arg_desc标识符两次。有没有一种方法可以声明变量并以某种方式传递它们。如?
EXECUTE format('INSERT INTO temp_$A($B, $C) SELECT DISTINCT $B, $C from staging_staff,
arg_table, arg_key, arg_desc);
我尝试过:
DECLARE
...
temp_table text;
BEGIN
...
temp_table:= CONCAT('temp_', arg_table);
INSERT INTO temp_table(arg_key, arg_desc) SELECT DISTINCT arg_key, arg_desc from staging_staff
但是PostgreSQL不喜欢这种语法。还有其他人想办法解决吗?
谢谢
编辑:我添加了所有正在使用的语句。采纳Laurenz的建议,并使用%s代替%I来表示串联的表名
答案 0 :(得分:1)
TG_ARGV
是参数化触发函数的唯一方法。
我真的看不到你的问题。懒惰是编程中的一种美德,因为它可以带来创新,但是您可以将它带走太多。
请注意,您格式的temp_%I
不能很好地工作。如果替换字符串不是常规标识符,您将得到类似temp_"CamelCase"
的东西,这不是标识符。
尝试将%s
格式与参数quote_ident('temp_' || arg_table)
一起使用。
答案 1 :(得分:1)
您可以使用positional format specifiers通过索引引用参数:
EXECUTE format(
'INSERT INTO %1$I(%2$I, %3$I) SELECT DISTINCT %2$I, %3$I FROM staging_staff',
'temp_' || arg_table, arg_key, arg_desc
);
如Laurenz所指出的,%I
说明符的输入应为完整的标识符名称,因此您需要将temp_
前缀附加到参数上,而不是将其嵌入格式字符串中。