繁体   English   中英

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

[英]How to derive column name in UPDATE from variable in a PL/pgSQL trigger function?

我在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等于列的值,其名称等于父表的名称”

纯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;

笔记

  • 如果列名实际上不存在,则会引发异常 除非您捕获它,否则您的事务将被回滚。

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

  • 始终确保动态SQL对SQL注入是安全的(在这种情况下由恶意制作的表名称)。 我用format()使用%I来防御它。

相关答案以及更多解释:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM