我想创建一个视图,对多个模式共有的表进行求和,如此处所示,并包含模式名称或派生表达式作为列,因此我创建了一个视图,其中包含模式名称作为常量值,通过使用quote_literal
将模式名称括在单引号中。
这里的函数可能quote_literal
不是正确的,但无论我做什么都会用双引号括起来。
CREATE OR REPLACE FUNCTION create_summary_view_quoted(
created_view text,
common_view text,
VARIADIC schemas text[]
) RETURNS text
LANGUAGE sql AS
$$SELECT format('CREATE VIEW %I AS ', created_view) ||
string_agg(
format('SELECT %I as source_schema, * FROM %I.%I ', quote_literal(schemas[i]) , schemas[i], common_view),
' UNION ALL '
)
FROM generate_series(1, cardinality(schemas)) AS i$$;
")
将其应用到查询中
SELECT create_summary_view_quoted('newv', 'oldv', 's1', 's2', 's3');
产生
create view newv as
select
"'s1'" as source_schema,
*
from
s1.oldv
union all
select
"'s2'" as source_schema,
*
from
s2.oldv
union all
select
"'s3'" as source_schema,
*
from
s3.oldv
问题是单引号常量周围的双引号导致 Postgres 将 is 视为列名并且它会崩溃。
我通过在第一个占位符周围使用双单引号并删除该函数来修复代码生成问题quote_literal
,
即替换
format('SELECT %I as source_schema, * FROM %I.%I ', quote_literal(schemas[i]) , schemas[i], common_view),
和
format('SELECT ''%I'' as source_schema, * FROM %I.%I ', schemas[i] , schemas[i], common_view),
我的问题不在于quote_literal
函数如何始终包装任何用双引号包装单引号字符串的函数的输出。
即使当我使用函数去除模式名称中的前导后缀(因为它们是多余的)时,单引号输出也会用双引号引起来。
例如,quote_nullable(right(schemas[i],-10))
结果字符串被双引号括起来。
我可以||
在某处应用运算符,但我更喜欢引用函数。
Postgres没有内置的单引号功能吗?
我是否缺少一些必需的 SQL 语法?
这是 Postgres 的怪癖吗?
格式
%I
类型说明符告诉format()
函数将相应的参数值视为标识符,并且由于它包含单引号(作为 的结果quote_literal()
),因此将其正确括在双引号中以使其成为有效标识符。但是,在
SELECT
列表中,您希望模式名称作为简单的字符串文字,因此%s
类型说明符将是合适的。quote_literal()
如果您知道模式名称的出处并且可以确保它们不包含任何单引号,也许您也可以省略: