Postgresql - 将整行返回为数组

时间:2012-07-13 10:53:17

标签: sql postgresql

有没有办法将以下结果转换为数组?

select pg_tables from pg_tables

这将仅返回一列,但数据类型不是数组。

编辑:我正在使用PostgreSql 9.1.4

更新:我需要等效的以下SQL语句,而不需要编写适用于每个表的列名:

select 
    string_to_array(
    schemaname || '|' ||
    tablename || '|' || 
    tableowner || '|' ||
    coalesce(tablespace,'') || '|' ||
    hasindexes || '|' ||
    hasrules || '|' ||
    hastriggers
    ,'|')
from 
    pg_tables

4 个答案:

答案 0 :(得分:9)

可能是这样:http://www.sqlfiddle.com/#!1/d41d8/364

select translate(string_to_array(x.*::text,',')::text,'()','')::text[] 
from pg_tables as x

如何运作(由内而外),5个步骤:

第一

select x.*::text from pg_tables as x;

示例输出:

|                                                            X |
----------------------------------------------------------------
|                    (pg_catalog,pg_statistic,postgres,,t,f,f) |
|                         (pg_catalog,pg_type,postgres,,t,f,f) |

第二

select string_to_array(x.*::text,',') from pg_tables as x;

示例输出:

|                           STRING_TO_ARRAY |
---------------------------------------------
| (pg_catalog,pg_statistic,postgres,,t,f,f) |
|      (pg_catalog,pg_type,postgres,,t,f,f) |

第三

select string_to_array(x.*::text,',')::text from pg_tables as x;

示例输出:

|                               STRING_TO_ARRAY |
-------------------------------------------------
| {(pg_catalog,pg_statistic,postgres,"",t,f,f)} |
|      {(pg_catalog,pg_type,postgres,"",t,f,f)} |

第四:

select translate( string_to_array(x.*::text,',')::text, '()', '') from pg_tables as x

示例输出:

|                                   TRANSLATE |
-----------------------------------------------
| {pg_catalog,pg_statistic,postgres,"",t,f,f} |
|      {pg_catalog,pg_type,postgres,"",t,f,f} |

最后:

select translate( string_to_array(x.*::text,',')::text, '()', '')::text[] 
from pg_tables as x

示例输出:

|                               TRANSLATE |
-------------------------------------------
| pg_catalog,pg_statistic,postgres,,t,f,f |
|      pg_catalog,pg_type,postgres,,t,f,f |

实时测试:http://www.sqlfiddle.com/#!1/d41d8/373

证明它有效:

with a as 
(
  select translate( string_to_array(x.*::text,',')::text, '()', '')::text[] as colArray 
  from pg_tables as x
)
select row_number() over(), unnest(colArray)
from a;

示例输出:

| ROW_NUMBER |                  UNNEST |
----------------------------------------
|          1 |              pg_catalog |
|          1 |            pg_statistic |
|          1 |                postgres |
|          1 |                         |
|          1 |                       t |
|          1 |                       f |
|          1 |                       f |
|          2 |              pg_catalog |
|          2 |                 pg_type |
|          2 |                postgres |
|          2 |                         |
|          2 |                       t |
|          2 |                       f |
|          2 |                       f |

答案 1 :(得分:6)

另一种方法,使用hstore类型,这样更健壮,可以解决字段值中的逗号

添加hstore contrib类型,执行一次:

CREATE EXTENSION hstore; 

创建此功能:

create or replace function hstore_to_array(r hstore) returns text[] as
$$
begin
    return array(select (each(r)).value);
end;
$$ language 'plpgsql';

然后试试这个:

select hstore_to_array(hstore(r)) from pg_tables r limit 10;

输出:

                  hstore_to_array                  
---------------------------------------------------
 {f,pg_statistic,t,pg_catalog,postgres,NULL,f}
 {f,pg_type,t,pg_catalog,postgres,NULL,f}
 {f,pg_attribute,t,pg_catalog,postgres,NULL,f}
 {f,xx,t,public,postgres,NULL,f}
 {f,yy,t,public,postgres,NULL,f}
 {f,tblx,f,public,postgres,NULL,f}
 {f,pg_authid,t,pg_catalog,postgres,pg_global,f}
 {f,pg_proc,t,pg_catalog,postgres,NULL,f}
 {f,pg_class,t,pg_catalog,postgres,NULL,f}
 {f,pg_database,t,pg_catalog,postgres,pg_global,f}
(10 rows)

另一个例子:

create table Beatle(firstname text, middlename text, lastname text);


insert into Beatle(firstname, middlename, lastname) values
('John','Winston','Lennon'),
('Paul','','McCartney'),
('George',NULL,'Harrison'),
('Ringo','my passions are ring,drum and shades','Starr');

查询:

select hstore_to_array(hstore(b)) from Beatle b;

输出:

                   hstore_to_array                    
------------------------------------------------------
 {Lennon,John,Winston}
 {McCartney,Paul,""}
 {Harrison,George,NULL}
 {Starr,Ringo,"my passions are ring,drum and shades"}
(4 rows)

正如我们所看到的,即使使用逗号的值也能正确保存。

精明的读者会注意到上面的输出。 hstore函数没有预先确定字段的原始顺序。为了保留它,将表放在子查询上,即

select hstore_to_array(hstore(b)) from (select * from Beatle) as b

输出:

                   hstore_to_array                    
------------------------------------------------------
 {John,Winston,Lennon}
 {Paul,"",McCartney}
 {George,NULL,Harrison}
 {Ringo,"my passions are ring,drum and shades",Starr}
(4 rows)

使用的参考文献:http://okbob.blogspot.com/2009/10/dynamic-access-to-record-fields-in.html

要观看的下一个功能:http://www.postgresonline.com/journal/archives/254-PostgreSQL-9.2-Preserving-column-names-of-subqueries.html


<强>更新

看起来通过子查询保留列排序只是一个侥幸。我尝试进行排序(例如,在名字上)。

select hstore_to_array(hstore(b)) 
from (select * from Beatle order by firstname) as b

输出不再保留原始列顺序:

                   hstore_to_array                    
------------------------------------------------------
 {Harrison,George,NULL}
 {Lennon,John,Winston}
 {McCartney,Paul,""}
 {Starr,Ringo,"my passions are ring,drum and shades"}
(4 rows)

将进一步调查如何保留原始列顺序。


<强>更新

如果您需要对表进行排序,为了保留原始列顺序,请将ORDER BY放在子查询之外:

select hstore_to_array(hstore(b)) 
from (select * from Beatle) as b order by firstname;

输出:

                   hstore_to_array                    
------------------------------------------------------
 {George,NULL,Harrison}
 {John,Winston,Lennon}
 {Paul,"",McCartney}
 {Ringo,"my passions are ring,drum and shades",Starr}
(4 rows)

现在正确。

从内存表中选择也有效:

select hstore_to_array(hstore(b)) 
from 
(
    select * from 
    (values
        ('John',1940,'Winston','Lennon'),
        ('Paul',1942,'','McCartney'),
        ('George',1943,NULL,'Harrison'),
        ('Ringo',1940,'my passions are ring,drum and shades','Starr')
    ) as x(Firstname,BirthYear,Middlename,Lastname)
) as b     
order by BirthYear desc, Firstname desc

输出:

                      hstore_to_array                      
-----------------------------------------------------------
 {George,1943,NULL,Harrison}
 {Paul,1942,"",McCartney}
 {Ringo,1940,"my passions are ring,drum and shades",Starr}
 {John,1940,Winston,Lennon}
(4 rows)

<强>更新

事实证明,功能hstore_to_array已经是内置功能,只需使用avalshttp://www.postgresql.org/docs/9.1/static/hstore.html

select 
    avals (hstore(b))
from 
(
    select * from 
    (values
        ('John',1940,'Winston','Lennon'),
        ('Paul',1942,'','McCartney'),
        ('George',1943,NULL,'Harrison'),
        ('Ringo',1940,'my passions are ring,drum and shades','Starr')
    ) as x(Firstname,BirthYear,Middlename,Lastname)
) as b 
order by BirthYear desc, Firstname desc;

输出:

                           avals                           
-----------------------------------------------------------
 {George,1943,NULL,Harrison}
 {Paul,1942,"",McCartney}
 {Ringo,1940,"my passions are ring,drum and shades",Starr}
 {John,1940,Winston,Lennon}
(4 rows)

另一个样本:

select avals(hstore(b)) 
from (select * from Beatle) as b order by Firstname;

输出:

                        avals
------------------------------------------------------
 {George,NULL,Harrison}
 {John,Winston,Lennon}
 {Paul,"",McCartney}
 {Ringo,"my passions are ring,drum and shades",Starr}
(4 rows)

只需使用avals

实时测试http://www.sqlfiddle.com/#!1/d41d8/388

请注意,虽然sqlfiddle输出没有数组指示符(花括号)和&#34上的双引号,但我的激情是响铃,鼓和阴影&#34; , avals结果是一个数组,其中带逗号的字符串在实际结果中有双引号,你可以在你的pgAdmin或psql上测试它

答案 2 :(得分:2)

此功能适用于所有极端情况,包括NULL值,空字符串或值中的特殊字符。

CREATE OR REPLACE FUNCTION f_rows_to_arr(_tbl text)
  RETURNS SETOF text[] AS
$BODY$
BEGIN

RETURN QUERY EXECUTE '
SELECT ARRAY[' || (
        SELECT string_agg(quote_ident(attname) || '::text', ',')
        FROM   pg_catalog.pg_attribute 
        WHERE  attrelid = _tbl::regclass  -- valid, visible table name 
        AND    attnum > 0                 -- exclude tableoid & friends
        AND    attisdropped = FALSE       -- exclude dropped columns
        ) || ' ]
FROM   ' || _tbl::regclass;

END;
$BODY$ LANGUAGE plpgsql;

呼叫:

SELECT * FROM f_rows_to_arr ('mytbl');

转换为regclass避免了SQLi。列未在此版本中排序。 有关this related answer中使用过的技巧和链接的更多说明。

答案 3 :(得分:0)

string_to_array可能有所帮助:

SELECT string_to_array(pg_tables::text,','::text) FROM pg_tables;