使用动态列名插入

INSERT with dynamic column names

我将列名存储在变量 colls 中,接下来我执行代码:

DO $$
DECLARE
v_name text :=  quote_ident('colls');
BEGIN
EXECUTE 'insert into table1 select '|| colls ||' from table2 ';
-- EXECUTE 'insert into table1 select '|| v_name ||' from table2 ';
END$$;

我遇到错误:列 "colls" 不存在。 程序使用 colls 作为名称而不是变量。我做错了什么?

我在文档中找到了类似的例子:
https://www.postgresql.org/docs/8.1/static/plpgsql-statements.html#PLPGSQL-STATEMENTS-EXECUTING-DYN

I have column names stored in variable colls

不,你不知道。您有一个变量 v_name - 它包含一个 单个 单词:'colls'。关于 SQL 中的变量:

  • User defined variables in PostgreSQL

阅读手册中的第 Identifiers and Key Words and Constants 章。

如果您在单个变量中有 多个 列名称,则不能那样使用 quote_ident()。它会将 整个 字符串转义为单个标识符。


我想基本的误解是这样的:'colls' 是一个 字符串常量 ,而不是 变量 。除了您在 DECLARE 部分中声明的变量外,DO 语句中没有其他变量。您可能正在寻找 一个将可变数量的列名作为参数的函数 ...

CREATE OR REPLACE FUNCTION f_insert_these_columns(VARIADIC _cols text[])
  RETURNS void AS
$func$
BEGIN
   EXECUTE (
      SELECT 'INSERT INTO table1 SELECT '
          || string_agg(quote_ident(col), ', ')
          || ' FROM table2'
      FROM   unnest(_cols) col
      );
END
$func$  LANGUAGE plpgsql;

通话:

SELECT f_insert_these_columns('abd', 'NeW Deal');          -- column names case sensitive!
SELECT f_insert_these_columns(VARIADIC '{abd, NeW Deal}'); -- column names case sensitive!

请注意我是如何取消嵌套列名数组并将它们转义的一个一个
VARIADIC 参数应该非常适合您的用例。您可以传递列名列表或数组。
无论哪种方式,都会因 SQL 注入而异。
相关,更多解释:

  • Pass multiple values in single parameter
  • Table name as a PostgreSQL function parameter