如何从 PostgreSQL 9.4 中的匿名行类型获取第一个字段?

问题描述 投票:0回答:5
=# SELECT row(0, 1) ;
  row
-------
 (0,1)
(1 row)

如何在同一查询中获取

0
?我想了下面的工作方式,但是有什么简单的方法吗?

=# SELECT json_agg(row(0, 1))->0->'f1';
?column?
----------
 0
(1 row)

类似数组的语法不太好

[0]

谢谢!

sql database postgresql row anonymous
5个回答
2
投票

您的行类型是匿名的,因此您无法轻松访问其元素。您可以做的是创建一个

TYPE
,然后将匿名行转换为该类型并访问该类型中定义的元素:

CREATE TYPE my_row AS (
  x integer,
  y integer
);

SELECT (row(0,1)::my_row).x;

就像 Craig Ringer 在您的问题中评论的那样,如果可以的话,您应该避免从一开始就生成匿名行,并输入您在数据模型和查询中使用的任何数据。


2
投票

如果您只想要任意行中的第一个元素,请将行转换为 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


1
投票

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 导入数组的工具,因此上面是通过主要正则表达式进行的粗略文本操作。也许有人会发现这很有用!


0
投票

使用 Postgresql 13+,您可以使用

.fN
表示法引用行中的各个元素。举个例子:

select (row(0, 1)).f1; --> returns 0.

请参阅 https://www.postgresql.org/docs/13/sql-expressions.html#SQL-SYNTAX-ROW-CONSTRUCTORS


0
投票

*我的答案解释了如何访问命名行的元素。

例如,您有一个匿名行(记录),如下所示:

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
    会得到 错误

© www.soinside.com 2019 - 2024. All rights reserved.