PostgreSQL的复杂数组字面量语法是什么?(如圆[])



PostgreSQL文档指出,虽然一些字面值有特殊的语法,但字面值的通用语法看起来像type 'data','data'::typeCAST('data' AS type)。例如,可以将整数16写成16'16'::int。美元报价也是允许的,所以$$16$$:int也可以工作。

对于某些类型,如circle,泛型语法(据我所知)是唯一的方式来编写文字。circle有四种语法:<(x, y), r>((x, y), r)(x, y), rx, y, r;然而,这些似乎都不能正常工作:

y=> create table t (c circle);
CREATE TABLE
y=> insert into t (c) values ( <(1,2),3> );
ERROR:  syntax error at or near "<"
LINE 1: insert into t (c) values ( <(1,2),3> );
^
y=> insert into t (c) values ( ((1,2),3) );
ERROR:  column "c" is of type circle but expression is of type record
LINE 1: insert into t (c) values ( ((1,2),3) );
^
HINT:  You will need to rewrite or cast the expression.
y=> insert into t (c) values ( (1,2),3 );
ERROR:  INSERT has more expressions than target columns
LINE 1: insert into t (c) values ( (1,2),3 );
^
y=> insert into t (c) values ( 1,2,3 );
ERROR:  INSERT has more expressions than target columns
LINE 1: insert into t (c) values ( 1,2,3 );
^

相反,使用泛型语法效果很好:

y=> insert into t (c) values ( '1,2,3' );
INSERT 0 1
y=> select c from t;
c
-----------
<(1,2),3>

还记录了数组语法,它以逗号分隔并以大括号括起来。例如,范围1-5可以写成'{1, 2, 3, 4, 5}'::int[]

不幸的是,数组语法似乎不支持用泛型语法指定的值:$${ 1 }$$::int[]被接受,但$${ '1'::int }::int[]被拒绝,$${ '1' }::int[]也是。

因为数组字面量语法不接受元素的泛型语法,而且因为泛型语法似乎是写圆圈字面量的唯一方法,所以在PostgreSQL中似乎不可能写圆圈字面量。

y=> select $${ }$$::circle[];
circle
--------
{}
(1 row)
y=> select $${ '<(1, 2), 3>'::circle }$$::circle[];
ERROR:  invalid input syntax for type circle: "'<(1"
LINE 1: select $${ '<(1, 2), 3>'::circle }$$::circle[];

真的是这样吗?


注意:是的,这是至关重要的,我想写一个circle[]文字。原因是我的用例是在PostgreSQL客户端中指定准备好的语句中的值,并且,正如PostgreSQL协议文档所说(强调我的):

参数数据类型可通过OID指定;如果没有给出,解析器尝试以与对未类型化的文字字符串常量相同的方式推断数据类型。.

这意味着,例如,ARRAY[ '<(1,2),3>'::circle ]不是一个有效的解决方案,因为它不使用字面语法。

解决方案很简单:转义逗号!

y=> select '{ <(1,2),3>, <(4,5),6> }'::circle[];
circle
---------------------------
{"<(1,2),3>","<(4,5),6>"}
(1 row)

还有一个选项是将元素双引号括起来:

y=> select '{ "<(1,2),3>", "<(4,5),6>" }'::circle[];
circle
---------------------------
{"<(1,2),3>","<(4,5),6>"}
(1 row)

感谢Github上的sehrope告诉我这一点。引用PostgreSQL文档的相关部分:

[…当写入数组值时,你可以在任何单独的数组元素周围使用双引号。如果元素值会混淆数组值解析器,则必须这样做。例如,包含花括号、逗号[…]],双引号,反斜杠,[等,]必须双引号。[…或者,您可以避免引号并使用反斜杠转义来保护所有数据字符,否则将被视为数组语法。

相关内容

最新更新