另一种方法,使用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
已经是内置功能,只需使用avals
:http ://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
ツ</p>
现场测试:http ://www.sqlfiddle.com/#!1/d41d8/388
请注意,虽然 sqlfiddle 输出没有数组指示符(大括号)和“我的激情是戒指,鼓和阴影”上的双引号,但 avals 结果是一个数组,其中带有逗号的字符串有双引号实际结果,您可以在 pgAdmin 或 psql 上对其进行测试