与先前 的一对一映射问题 类似,我需要一个针对源和目标中多列的解决方案。
仍可与Postgres 9.4.4一起使用,对查询和架构进行了修改,如下所示:
假设我有这两个表Table1
和Table2
:
Create table Table1(col1 int, col2 varchar(100), col3 varchar(100));
Create table Table2(col1 int, col2 varchar(100), col3 varchar(100));
还有另一个表,Table3
用于存储将数据从迁移Table1
到的公式Table2
:
CREATE TABLE Table3 (
tbl_src character varying(200),
col_src character varying(500),
tbl_des character varying(200),
col_des character varying(100),
condition character varying(500)
);
Insert into Table3(tbl_src, col_src, tbl_des, col_des, condition)
VALUES ('Table1','col1','Table2','col1', 'WHERE col1>=1')
, ('Table1','col2','Table2','col2', NULL)
, ('Table1','col3','Table2','col3', NULL);
如何在动态查询中编译此公式并将其插入目标表?
动态查询多列语句的基本查询-忽略该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 sql
FROM table3
WHERE 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 sql
FROM table3
WHERE 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 sql
FROM table3
WHERE 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;
问题内容: 我的Postgres版本是: “PostgreSQL 9.4.4, compiled by Visual C++ build 1800, 32-bit” 假设我有两个表Table1和Table2,分别具有columncol1和col2。 还有另一个表,Table3用于存储将数据从迁移Table1到的公式Table2: 如何在动态查询中编译此公式并将其插入目标表? 问题答案: 动态构建命
问题内容: 我想在具有动态列的表中添加值。我设法用动态列创建了一个表,但无法弄清楚如何插入数据。 问题答案: 您还可以使用数据库元数据获取列名。这样的好处是,您甚至不需要知道列名,而是可以在您的代码中动态检索它们。 一旦有了列名,就可以像平常一样使用它(List.size()当然会给出列数)。 更新: 此代码假定您将正确类型的对象传递给PreparedStatement.setObject(Obj
问题内容: 我已经徒劳地搜索了很长时间,不得不承认失败并寻求帮助,我正在尝试修改数据透视查询,以从具有以下数据的表中生成结果的动态查询: 为了显示这样的内容,其中页码列取决于用户访问的页面数: 我已经通过对列中的硬编码进行了管理,但是显然我不想继续更改脚本以容纳越来越多的页面。 到目前为止,我有一些类似的东西: 任何帮助或正确方向的指点将不胜感激! 提前致谢! 问题答案: 我所看到的关于动态枢轴的
问题内容: 我试图找到一种方法来返回具有动态列数的记录集。我可以编写一个查询来生成需要的列名列表,如下所示: 这将返回一个简短的列表,例如’poke’,’prod’,’hit’,’drop’等。然后,我希望生成一个表,其中显示了一系列测试,其中每个测试都在其中运行。每天早晨,我们查看开发人员的工作并对其进行戳戳和刺戳,以便每天进行每次测试。我可以静态编写此查询: 但是,这是硬编码到我们每天运行的测
我正在做一个自动数据库填充程序,我遇到了一个我无法理解的错误。 我正在开发一个脚本,它应该处理大量文件,包含多个值。文件中的信息具有以下结构: id time_stamp(值1值2值3值4值5)*i(值1值2值3值4值5)*n(值1值2) - I和n (n = nGrupos)是已知的,I从1变化到I,n从1变化到2。每个括号集将被插入到不同的表中,因此有以下5个值。 我遇到麻烦的代码是(我不能让
问题内容: 我试图使用临时表开发此存储过程,但是那行不通,所以我改用表变量。我需要对表变量执行临时动态查询,然后使用该表变量执行最终查询。问题是我收到错误消息“必须声明标量变量@clms”。我假设Exec没有该表变量的作用域? 问题答案: 这是简单的最小示例。您可以使用语句。关键是要在动态查询的内部和外部声明表变量。在动态查询结束时,只需从表变量中选择并将结果集插入外部表变量中即可: