我在PostgreSQL 9.4中有一个简单的触发器函数:
BEGIN
IF (TG_OP = 'UPDATE') THEN
UPDATE relation
SET child_name = new.name
WHERE table_reference_1 = new.id;
END IF;
RETURN NULL;
END;
是否可以用变量替换table_reference_1(列名)?我想做的事情如下:
BEGIN
IF (TG_OP = 'UPDATE') THEN
UPDATE relation
SET child_name = new.name
WHERE TG_TABLE_NAME = new.id;
END IF;
RETURN NULL;
END;
在哪里TG_TABLE_NAME = new.id应该是指:
“new.id等于列的值,其名称等于父表的名称”.
最佳答案 纯SQL不接受标识符的变量.我看到了触发器功能的两个选项:
1. CASE表达
对于一些已知的替代品(以及可选的全能).
UPDATE relation r
SET child_name = NEW.name
WHERE CASE TG_TABLE_NAME -- "switched case"
WHEN 'possible_column1' -- value!
THEN r.possible_column1 = NEW.id -- identifier!
WHEN 'possible_column2'
THEN r.possible_column2 = NEW.id
-- etc.
-- ELSE r.default_column = NEW.id
-- or no ELSE ...
END;
没有ELSE意味着如果没有选项匹配,表达式的计算结果为NULL.并且只有TRUE符合WHERE子句.
2.动态SQL
对于任何数量的替代品或编码时未知的替代品.
EXECUTE format('
UPDATE relation
SET child_name = $1
WHERE %I = $2'
, TG_TABLE_NAME -- being used as column name
USING NEW.name, NEW.id;
笔记
>如果列名实际上不存在,则会引发异常.您的交易将回滚unless you trap it.
> PL / pgSQL使用预处理语句进行操作.如果Postgres发现重新规划不会产生比通用计划更好的计划,则可以在同一会话中重用选项1的查询计划.每次都计划选项2.根据您的使用情况,这可能是无关紧要/不利/实际优势……
> Difference between language sql and language plpgsql in PostgreSQL functions
>始终确保动态SQL对SQL注入是安全的(在这种情况下由恶意制作的表名称).我用format()
使用%I防御它.
相关答案以及更多解释:
> Table name as a PostgreSQL function parameter
> INSERT with dynamic table name in trigger function
> Update multiple columns in a trigger function in plpgsql
> Difference between language sql and language plpgsql in PostgreSQL functions