在PostgreSQL的触发器函数中重用标识符

在PostgreSQL的触发器函数中重用标识符,postgresql,function,triggers,Postgresql,Function,Triggers,我正在使用PostgreSQL 9.2.23。 我有一个触发器函数,它有许多语句,这些语句在format语句中重用相同的标识符。为了简洁起见,我将只包含一个execute语句 CREATE OR REPLACE FUNCTION update_lookup_table() RETURNS trigger AS $BODY$ DECLARE arg_key text; arg_desc text; arg_table text;

我正在使用PostgreSQL 9.2.23。 我有一个触发器函数,它有许多语句,这些语句在format语句中重用相同的标识符。为了简洁起见,我将只包含一个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个标识符反复出现。 正如您在我的format语句中看到的,我重复使用了arg_键和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

TG_ARGV
是参数化触发器函数的唯一方法

我真的不明白你的问题。懒惰是编程中的一种美德,因为它会带来创新,但你可能会走得太远

顺便说一句,您的格式中的
temp_u%I
将无法正常工作。如果替换字符串不是常规标识符,那么您将得到类似于
temp_uu“CamelCase”
的东西,它不是标识符

尝试将
%s
格式与参数
quote_ident('temp| | arg_table)
一起使用,您可以使用该格式按索引引用参数:

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
前缀附加到参数中,而不是将其嵌入格式字符串中。

感谢您的帮助。我想大多数时候这都不是问题,因为它仍然可以正常工作。我想也许我可以让我的代码干涸一点。例如,我在函数中有一个语句,我在原始问题中没有包含它,但我将添加它只是为了显示它可以得到多长时间。谢谢,这就是我要找的!