=# SELECT row(0, 1) ;
row
-------
(0,1)
(1 row)
如何在同一查询中获取
0
?我想了下面的工作方式,但是有什么简单的方法吗?
=# SELECT json_agg(row(0, 1))->0->'f1';
?column?
----------
0
(1 row)
类似数组的语法不太好
[0]
。
谢谢!
您的行类型是匿名的,因此您无法轻松访问其元素。您可以做的是创建一个
TYPE
,然后将匿名行转换为该类型并访问该类型中定义的元素:
CREATE TYPE my_row AS (
x integer,
y integer
);
SELECT (row(0,1)::my_row).x;
就像 Craig Ringer 在您的问题中评论的那样,如果可以的话,您应该避免从一开始就生成匿名行,并输入您在数据模型和查询中使用的任何数据。
如果您只想要任意行中的第一个元素,请将行转换为 JSON 并选择 f1...
SELECT row_to_json(row(0,1))->'f1'
或者,如果您总是有两个整数或严格的结构,您可以创建一个临时表(或类型)和一个选择第一列的函数。
CREATE TABLE tmptable(f1 int, f2 int);
CREATE FUNCTION gettmpf1(tmptable) RETURNS int AS 'SELECT $1.f1' LANGUAGE SQL;
SELECT gettmpf1(ROW(0,1));
资源:
https://www.postgresql.org/docs/9.2/static/functions-json.html https://www.postgresql.org/docs/9.2/static/sql-expressions.html
json 解决方案非常优雅。只是为了好玩,这是一个使用正则表达式的解决方案(更丑陋):
WITH r AS (SELECT row('quotes, "commas",
and a line break".',null,null,'"fourth,field"')::text AS r)
--WITH r AS (SELECT row('',null,null,'')::text AS r)
--WITH r AS (SELECT row(0,1)::text AS r)
SELECT CASE WHEN r.r ~ '^\("",' THEN ''
WHEN r.r ~ '^\("' THEN regexp_replace(regexp_replace(regexp_replace(right(r.r, -2), '""', '\"', 'g'), '([^\\])",.*', '\1'), '\\"', '"', 'g')
ELSE (regexp_matches(right(r.r, -1), '^[^,]*'))[1] END
FROM r
将行转换为文本时,PostgreSQL 使用带引号的 CSV 格式。我找不到任何用于将引用的 CSV 导入数组的工具,因此上面是通过主要正则表达式进行的粗略文本操作。也许有人会发现这很有用!
使用 Postgresql 13+,您可以使用
.fN
表示法引用行中的各个元素。举个例子:
select (row(0, 1)).f1; --> returns 0.
请参阅 https://www.postgresql.org/docs/13/sql-expressions.html#SQL-SYNTAX-ROW-CONSTRUCTORS
*我的答案解释了如何访问命名行的元素。
例如,您有一个匿名行(记录),如下所示:
postgres=# SELECT ROW(2,'David',32);
row
--------------
(2,David,32)
(1 row)
现在,您可以创建
person
类型,如下所示:
CREATE TYPE person AS (
id INTEGER,
name VARCHAR(20),
age INTEGER
);
然后,您可以使用
person
类型访问匿名行的元素,如下所示:
postgres=# SELECT (ROW(2,'David',32)::person).id;
id
----
2
(1 row)
postgres=# SELECT (ROW(2,'David',32)::person).name;
name
-------
David
(1 row)
postgres=# SELECT (ROW(2,'David',32)::person).age;
age
-----
32
(1 row)
或者,您可以使用
.fx
访问匿名行(记录)的元素,如下所示:
postgres=# SELECT (ROW(2,'David',32)).f1;
f1
----
2
(1 row)
postgres=# SELECT (ROW(2,'David',32)).f2::VARCHAR(20);
f2
-------
David
(1 row)
postgres=# SELECT (ROW(2,'David',32)).f3;
f3
----
32
(1 row)
*备注:
在匿名行中,第一个元素是
f1
,第二个元素是 f2
...
从
::VARCHAR(20)
中省略 f2
会得到 错误。