如何在PL / pgSQL触发器函数中从变量派生UPDATE中的列名?

时间:2015-12-24 09:33:20

标签: sql postgresql triggers plpgsql dynamic-sql

我在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; 

WHERE TG_TABLE_NAME = new.id应该是这样的意思:
new.id等于列的值,其名称等于父表的名称”

1 个答案:

答案 0 :(得分:2)

Plain SQL不接受标识符的变量。我看到了触发器功能的两个选项:

1。 product(*(imap(str.rstrip,f1),imap(str.rstrip, f2)) 表达式

对于一些已知的替代品(以及可选的全能)。

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; 表示如果没有选项匹配,表达式的计算结果为NULL。只有ELSE符合TRUE条款。

2。动态SQL

对于任何数量的替代品或编码时未知的替代品。

WHERE

注释

  • 如果列名实际上不存在,则会引发异常。您的交易将回滚unless you trap it

  • PL / pgSQL使用预准备语句进行操作。如果Postgres发现重新规划不会产生比通用计划更好的计划,则可以在同一会话中重用选项1 的查询计划。选项2计划每次。根据您的使用情况,这可能是不相关的/不利的/实际的优势......

  • 始终确保动态SQL对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; 使用%I进行防御。

相关答案以及更多解释: