提问人:Ivan Vodopyanov 提问时间:8/9/2023 最后编辑:Erwin BrandstetterIvan Vodopyanov 更新时间:8/9/2023 访问量:67
字符串连接与美元报价
String concatenation with dollar-quoting
问:
我使用串联来准备一个带有参数值的查询字符串
当我使用单引号时:
p_ReqStr_old := '
with prm as
(
select
1::int4 as id, ' || '
to_timestamp(''' || to_char(p_BegRepDate, 'DD.MM.YYYY') || ''',''DD.MM.YYYY'')::timestamp as p_BegDate,
to_timestamp(''' || to_char(p_EndRepDate, 'DD.MM.YYYY') || ''',''DD.MM.YYYY'')::timestamp as p_EndDate, ' ||
cast(p_IsIncludeTestLpu as varchar(1)) || '::int8 as p_IsIncludeTestLpu
)';
我收到以下结果:
with prm as
(
select
1::int4 as id,
to_timestamp('01.01.2023','DD.MM.YYYY')::timestamp as p_BegDate,
to_timestamp('31.01.2023','DD.MM.YYYY')::timestamp as p_EndDate, 2::int8 as p_IsIncludeTestLpu
)
当我使用美元报价时:
p_ReqStr_new := $$
with prm as
(
select
1::int4 as id,
to_timestamp(to_char(p_BegRepDate, 'DD.MM.YYYY'), 'DD.MM.YYYY')::timestamp as p_BegDate,
to_timestamp(to_char(p_EndRepDate, 'DD.MM.YYYY'), 'DD.MM.YYYY')::timestamp as p_EndDate,
cast(p_IsIncludeTestLpu as varchar(1))::int8 as p_IsIncludeTestLpu
)$$;
我收到这个不良结果:
with prm as
(
select
1::int4 as id,
to_timestamp(to_char(p_BegRepDate, 'DD.MM.YYYY'), 'DD.MM.YYYY')::timestamp as p_BegDate,
to_timestamp(to_char(p_EndRepDate, 'DD.MM.YYYY'), 'DD.MM.YYYY')::timestamp as p_EndDate,
cast(p_IsIncludeTestLpu as varchar(1))::int8 as p_IsIncludeTestLpu
)
有没有办法通过美元报价机制接收带有日期值的结果?
答:
2赞
jjanes
8/9/2023
#1
当您切换到美元报价时,您还删除了串联。如果你想保持串联,那就保留它。这确实意味着您需要继续关闭和重新打开两边的美元报价,就像使用单引号时一样。切换引号只是意味着您不再需要转义字面上的单引号,它不会改变串联的工作方式。||
也许你应该改用 FORMAT 函数。
评论
0赞
Ivan Vodopyanov
8/10/2023
谢谢你的快速回答。我更新了我在引用和串联方面的知识。是的,它有效!我已将所有单引号替换为$$
2赞
Erwin Brandstetter
8/9/2023
#2
请参阅jjanes关于对美元报价的误解的回答。
假设这是关于 PL/pgSQL 代码块中使用 EXECUTE 的动态 SQL,您不需要任何美元引号(函数体的外部引号除外),也不需要串联。使用子句传递值更便宜、更安全:USING
演示:
DO
$do$
DECLARE
p_BegRepDate timestamp := '2023-01-01';
p_EndRepDate timestamp := '2023-01-31';
p_IsIncludeTestLpu text := '234'; -- ??
BEGIN
EXECUTE
$q$ -- no nested ', could just be plane '
WITH prm AS (
SELECT 1::int4 AS id
, $1 AS p_begdate
, $2 AS p_enddate
, $3 AS p_is_include_test_lpu
)
TABLE prm
$q$
USING p_BegRepDate, p_EndRepDate -- assuming these are type timestamp already
, (p_IsIncludeTestLpu::varchar(1))::int8 -- can probably be simplified, too
;
END
$do$;
相关:
评论
0赞
Ivan Vodopyanov
8/10/2023
谢谢你,欧文,关键词的例子。就我而言,我重新创建了一个动态 SQL 并传入函数。我想我不能用于这个目的。USING
dblink()
EXECUTE
1赞
Erwin Brandstetter
8/10/2023
@Ivan:可以执行整个调用,但不能以这种方式将值传递到远程查询字符串中。即便如此,您的代码也可以简化一点。你会用必要的细节开始一个新问题......EXECUTE
评论