动态查询多列语句的基本查询-忽略该
condition列:
SELECt format( 'INSERT INTO %I (%s) SELECT %s FROM %I' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg(quote_ident(col_src), ', ') , tbl_src) AS sqlFROM table3WHERe tbl_des = 'Table2'AND tbl_src = 'Table1'GROUP BY tbl_des, tbl_src;
结果:
INSERT INTO "Table2" (col1, col2, col3)SELECt CASE col1, col2, col3 FROM "Table1"
这假定了一个 _ 单一的 源和一个 _ 单一的
目标表。否则事情会变得更加复杂。我添加了一些
WHERe条件以使其清楚。
以上仍然忽略了
condition。首先,不要
WHERe在该
condition列中包含关键字。那只是噪音而已,无济于事:
INSERT INTO Table3(tbl_src, col_src, tbl_des, col_des, condition)VALUES ('Table1','col1','Table2','col1', **'col1 >=1'**) -- without WHERe! , ('Table1', ...警告
这种方法本质上是不安全的。该
condition持有表达式需要被连接起来“为是”,那么你是完全开放的 SQL注入攻击
。您需要确保不受信任的用户无法以
table3任何方式写信来避免这种情况。
在此基础上,假设每个条件 仅适用于其各自的列 ,我们可以通过将列包装在
CASE表达式中来解决它:
SELECt format( 'INSERT INTO %I (%s) SELECT %s FROM %I' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg( CASE WHEN condition IS NULL THEN quote_ident(col_src) ELSE format('CASE WHEN %s THEN %I END' , condition, col_src) -- condition is unsafe! END, ', ') , tbl_src) AS sqlFROM table3WHERe tbl_des = 'Table2'AND tbl_src = 'Table1'GROUP BY tbl_des, tbl_src;产生以下形式的声明:
INSERT INTO "Table2" (col1, col2, col3)SELECt CASE WHEN col1>=1 THEN col1 END, col2, col3 FROM "Table1"
或者,就像您在以后的注释中添加的一样,条件可以 应用于整个行 。从逻辑上讲,这是另一个灰色区域。条件存储在特定的列中,但适用于整行…
尽管如此,您可以在
WHERe子句中添加通用条件。
SELECt format( 'INSERT INTO %I (%s) SELECT %s FROM %I%s' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg(quote_ident(col_src), ', ') , tbl_src , ' WHERe ' || string_agg(condition, ' AND ')) AS sqlFROM table3WHERe tbl_des = 'Table2'AND tbl_src = 'Table1'GROUP BY tbl_des, tbl_src;
条件是AND的,并且
WHERe仅在有条件的情况下才添加子句-否则,结果NULL值将吞噬表达式中添加的关键字
' WHERe ' ||string_agg(condition, ' AND '))
在
DO命令或plpgsql函数中使用此命令可以动态执行,就像我之前的答案中所指示的那样
plpgsql基本功能:
CREATE OR REPLACe FUNCTION f_test() RETURNS void AS$func$BEGIN EXECUTE ( SELECT format( 'INSERT INTO %I (%s) SELECT %s FROM %I%s' , tbl_des , string_agg(quote_ident(col_des), ', ') , string_agg(quote_ident(col_src), ', ') , tbl_src , ' WHERe ' || string_agg(condition, ' AND ')) AS sql FROM table3 WHERe tbl_des = 'Table2' AND tbl_src = 'Table1' GROUP BY tbl_des, tbl_src );END$func$ LANGUAGE plpgsql;



