Dynamically access column value in record

只谈情不闲聊 提交于 2020-01-05 02:48:19

问题


Is it possible to dynamically access a column value from a record by its name?

I'm writing a trigger function that executes a dynamic SQL command and I would like to dynamically extract a column value from a NEW record by column name.

Here's a simplified example of what I'm trying to do:

$$
DECLARE
   command text := 'UPDATE $1 SET $2 = $3';
   myColumn := 'votes'
BEGIN
   EXECUTE command using 'anotherTable', myColumn, NEW.myColumn;
END
$$

回答1:


That's possible, but the USING clause of EXECUTE can only pass values.
While identifiers like table and column names must be concatenated (be wary of SQL injection!) before executing the command. Using format() (Postgres 9.1+) it could work like this:

$$
DECLARE
   _command text := 'UPDATE %I SET %I = $1 WHERE ....'; -- add WHERE condition
   _col text := 'votes';
BEGIN
   EXECUTE format(_command, 'anotherTable', _col)
   USING  NEW.myColumn;
END
$$;

Fixed a couple of minor problems in passing.

It must be mentioned that NEW is only available in trigger functions.

Be aware that 'anotherTable' is case sensitive here (being converted and escaped from a string), while NEW.myColumn is not (processed as identifier). Use legal, lower case, unquoted identifiers in Postgres to make your life easier.

Related answers with more explanation and links:

  • PL/pgSQL: General Way to Update N Columns in Trigger?
  • INSERT with dynamic table name in trigger function
  • Table name as a PostgreSQL function parameter
  • Are PostgreSQL column names case-sensitive?

To dynamically extract a column value from a NEW record by column name.

... you can use the hstore #= operator:

  • How to set value of composite variable field using dynamic SQL

Or you can make it work with standard features of dynamic SQL as well:

$$
DECLARE
   _col text := 'votes';
   _new_col text := 'column_name_in_new';  -- enter column name here, case sensitive
BEGIN
   EXECUTE format(
       'UPDATE %I SET %I = $1.%I WHERE ... '  -- add WHERE condition
     , 'anotherTable', _col, _new_col)
   USING  NEW;  -- pass whole row
END
$$;

Related:

  • Creating a trigger for child table insertion returns confusing error


来源:https://stackoverflow.com/questions/32490615/dynamically-access-column-value-in-record

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!