具有 EXECUTE 和嵌套格式的动态 SQL
Dynamic SQL with EXECUTE and nested format()
我试着用普通的 CTE(没有 EXECUTE ... FORMAT
)做到这一点,我能够做到。
我基本上有一个 table,它有大约 5 列,每列中有一些我想连接的数据,例如 manifest/generate 新列中的一些数据。
我可以做这样的事情并且有效:
WITH cte AS (SELECT *, case
when var1 = '' then ''
when var2 = '' then ''
else '' end, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')
INSERT INTO my_new_table
SELECT *, 'This is the new column I want to make with some data from my CTE' || c.type
FROM cte c;
所以这就像我说的那样有效。我最终会得到一个新的 table,它有一个额外的列,其中有一个硬编码的连接字符串 This is the new column I want to make with some data from my CTE Java
当然,在加载 SELECT
时,CTE 中相应行的 c.type
列中的任何内容都会连接到该字符串。
问题是,一旦我开始使用 EXECUTE...FORMAT
使它更干净并且对来自不同列的 concatenate/combined 不同数据片段有更多的能力(我的数据有点分散格式错误,我正在填充一个全新的 table),就好像 FORMAT 参数或变量无法检测到 CTE table.
我就是这样做的
EXECUTE FORMAT ('WITH cte AS (SELECT *, case
when var1 = %L then %L
when var2 = '' '' then '' ''
else '' '' end, ''adding_dummy_text_column''
FROM some_other_table sot
WHERE sot.type = ''java'')
INSERT INTO my_new_table
SELECT *, ''This is the new column I want to make with some data from my CTE %I''
FROM cte c', 'word1', 'word2', c.type
);
好的,所以我知道我在这个例子中使用了空字符串 '' ''
和 %L
但我只是想表明我没有任何问题。当我尝试引用我的 CTE 列时,您可以看到我正在尝试进行相同的串联,但通过利用 EXECUTE...FORMAT
并使用 %I
标识符。因此,前 2 个参数很好,它的 c.type
无论我尝试哪一列,都不起作用。此外,我删除了 c
别名并且没有得到任何更好的运气。不过,每当我引用 CTE 上的列时它都是 100%,因为我已经删除了所有这些代码并且没有它它运行得很好。
但是,是的,有什么变通办法吗?我真的很想转换一些数据,现在必须做 ||用于串联。
应该这样做:
EXECUTE format($f$WITH cte AS (SELECT *, CASE
WHEN var1 = %L THEN %L
WHEN var2 = ' ' THEN ' '
ELSE ' ' END, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')
INSERT INTO my_new_table
SELECT *, format('This is the new column I want to make with some data from my CTE %%I', c.type)
FROM cte c$f$
, 'word1', 'word2');
有两个级别。您需要第二个 format()
由第一个 format()
.
连接的动态 SQL 字符串执行
我用 dollar-quoting 进行了简化。参见:
- Insert text with single quotes in PostgreSQL
嵌套的 %
字符必须通过加倍来转义:%%I
。参见:
- What does %% in PL/pgSQL mean?
生成并执行此 SQL 语句:
WITH cte AS (SELECT *, CASE
WHEN var1 = 'word1' THEN 'word2'
WHEN var2 = ' ' THEN ' '
ELSE ' ' END, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')
INSERT INTO my_new_table
SELECT *, format('This is the new column I want to make with some data from my CTE %I', c.type)
FROM cte c
可以简化和改进为以下等价物:
INSERT INTO my_new_table(co1, col2, ...) -- provide target column list!
SELECT *
, CASE WHEN var1 = 'word1' THEN 'word2'
WHEN var2 = ' ' THEN ' '
ELSE ' ' END
, 'adding_dummy_text_column'
, format('This is the new column I want to make with some data from my CTE %I', sot.type)
FROM some_other_table sot
WHERE sot.type = 'java'
关于缺失的目标列列表:
- Cannot create stored procedure to insert data: type mismatch for serial column
您可以使用一个命令,创建并插入到新的 table!
create table my_new_table as
select *
, CASE WHEN var1 = 'hello' THEN 'word2'
WHEN var2 = ' ' THEN 'var2 is empty'
ELSE ' ' END adding_dummy_text_column
, format(
'This is the new column I want to make with some data from my CTE %I', sot.type)
from some_other_table sot
where sot.type ='java';
我试着用普通的 CTE(没有 EXECUTE ... FORMAT
)做到这一点,我能够做到。
我基本上有一个 table,它有大约 5 列,每列中有一些我想连接的数据,例如 manifest/generate 新列中的一些数据。
我可以做这样的事情并且有效:
WITH cte AS (SELECT *, case
when var1 = '' then ''
when var2 = '' then ''
else '' end, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')
INSERT INTO my_new_table
SELECT *, 'This is the new column I want to make with some data from my CTE' || c.type
FROM cte c;
所以这就像我说的那样有效。我最终会得到一个新的 table,它有一个额外的列,其中有一个硬编码的连接字符串 This is the new column I want to make with some data from my CTE Java
当然,在加载 SELECT
时,CTE 中相应行的 c.type
列中的任何内容都会连接到该字符串。
问题是,一旦我开始使用 EXECUTE...FORMAT
使它更干净并且对来自不同列的 concatenate/combined 不同数据片段有更多的能力(我的数据有点分散格式错误,我正在填充一个全新的 table),就好像 FORMAT 参数或变量无法检测到 CTE table.
我就是这样做的
EXECUTE FORMAT ('WITH cte AS (SELECT *, case
when var1 = %L then %L
when var2 = '' '' then '' ''
else '' '' end, ''adding_dummy_text_column''
FROM some_other_table sot
WHERE sot.type = ''java'')
INSERT INTO my_new_table
SELECT *, ''This is the new column I want to make with some data from my CTE %I''
FROM cte c', 'word1', 'word2', c.type
);
好的,所以我知道我在这个例子中使用了空字符串 '' ''
和 %L
但我只是想表明我没有任何问题。当我尝试引用我的 CTE 列时,您可以看到我正在尝试进行相同的串联,但通过利用 EXECUTE...FORMAT
并使用 %I
标识符。因此,前 2 个参数很好,它的 c.type
无论我尝试哪一列,都不起作用。此外,我删除了 c
别名并且没有得到任何更好的运气。不过,每当我引用 CTE 上的列时它都是 100%,因为我已经删除了所有这些代码并且没有它它运行得很好。
但是,是的,有什么变通办法吗?我真的很想转换一些数据,现在必须做 ||用于串联。
应该这样做:
EXECUTE format($f$WITH cte AS (SELECT *, CASE
WHEN var1 = %L THEN %L
WHEN var2 = ' ' THEN ' '
ELSE ' ' END, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')
INSERT INTO my_new_table
SELECT *, format('This is the new column I want to make with some data from my CTE %%I', c.type)
FROM cte c$f$
, 'word1', 'word2');
有两个级别。您需要第二个
连接的动态 SQL 字符串执行format()
由第一个format()
.我用 dollar-quoting 进行了简化。参见:
- Insert text with single quotes in PostgreSQL
嵌套的
%
字符必须通过加倍来转义:%%I
。参见:- What does %% in PL/pgSQL mean?
生成并执行此 SQL 语句:
WITH cte AS (SELECT *, CASE
WHEN var1 = 'word1' THEN 'word2'
WHEN var2 = ' ' THEN ' '
ELSE ' ' END, 'adding_dummy_text_column'
FROM some_other_table sot
WHERE sot.type = 'java')
INSERT INTO my_new_table
SELECT *, format('This is the new column I want to make with some data from my CTE %I', c.type)
FROM cte c
可以简化和改进为以下等价物:
INSERT INTO my_new_table(co1, col2, ...) -- provide target column list!
SELECT *
, CASE WHEN var1 = 'word1' THEN 'word2'
WHEN var2 = ' ' THEN ' '
ELSE ' ' END
, 'adding_dummy_text_column'
, format('This is the new column I want to make with some data from my CTE %I', sot.type)
FROM some_other_table sot
WHERE sot.type = 'java'
关于缺失的目标列列表:
- Cannot create stored procedure to insert data: type mismatch for serial column
您可以使用一个命令,创建并插入到新的 table!
create table my_new_table as
select *
, CASE WHEN var1 = 'hello' THEN 'word2'
WHEN var2 = ' ' THEN 'var2 is empty'
ELSE ' ' END adding_dummy_text_column
, format(
'This is the new column I want to make with some data from my CTE %I', sot.type)
from some_other_table sot
where sot.type ='java';