Is there a way how you can cast the following result to array?
select pg_tables from pg_tables
This will return one column only, however the da
string_to_array might help:
SELECT string_to_array(pg_tables::text,','::text) FROM pg_tables;
Another approach, use hstore
type, this is more robust, can solve the comma in a field's value
Add the hstore
contrib type, by executing this once:
CREATE EXTENSION hstore;
Create this function:
create or replace function hstore_to_array(r hstore) returns text[] as
$$
begin
return array(select (each(r)).value);
end;
$$ language 'plpgsql';
Then try this:
select hstore_to_array(hstore(r)) from pg_tables r limit 10;
Output:
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)
Another example:
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');
Query:
select hstore_to_array(hstore(b)) from Beatle b;
Output:
hstore_to_array
------------------------------------------------------
{Lennon,John,Winston}
{McCartney,Paul,""}
{Harrison,George,NULL}
{Starr,Ringo,"my passions are ring,drum and shades"}
(4 rows)
As we can see, even the value with comma is preserved properly.
An astute reader will notice something on the above output though. The hstore function doesn't preseve the original order of fields. In order to preserve it, put the table on subquery, i.e.
select hstore_to_array(hstore(b)) from (select * from Beatle) as b
Output:
hstore_to_array
------------------------------------------------------
{John,Winston,Lennon}
{Paul,"",McCartney}
{George,NULL,Harrison}
{Ringo,"my passions are ring,drum and shades",Starr}
(4 rows)
References used: http://okbob.blogspot.com/2009/10/dynamic-access-to-record-fields-in.html
Next feature to watch: http://www.postgresonline.com/journal/archives/254-PostgreSQL-9.2-Preserving-column-names-of-subqueries.html
UPDATE
It looks like the preservation of column ordering via subquery is just a fluke. I tried putting a sorting(e.g. on firstname).
select hstore_to_array(hstore(b))
from (select * from Beatle order by firstname) as b
The output doesn't preserve the original columns order anymore:
hstore_to_array
------------------------------------------------------
{Harrison,George,NULL}
{Lennon,John,Winston}
{McCartney,Paul,""}
{Starr,Ringo,"my passions are ring,drum and shades"}
(4 rows)
Will investigate further how to preserve original columns order.
UPDATE
If you need sort the table, in order to preserve the original columns order, put the ORDER BY
outside of subquery:
select hstore_to_array(hstore(b))
from (select * from Beatle) as b order by firstname;
Output:
hstore_to_array
------------------------------------------------------
{George,NULL,Harrison}
{John,Winston,Lennon}
{Paul,"",McCartney}
{Ringo,"my passions are ring,drum and shades",Starr}
(4 rows)
It's correct now.
And selecting from in-memory table works too:
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
Output:
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)
UPDATE
It turns out functionality hstore_to_array
is a built-in functionality already, just use 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;
Output:
avals
-----------------------------------------------------------
{George,1943,NULL,Harrison}
{Paul,1942,"",McCartney}
{Ringo,1940,"my passions are ring,drum and shades",Starr}
{John,1940,Winston,Lennon}
(4 rows)
Another sample:
select avals(hstore(b))
from (select * from Beatle) as b order by Firstname;
Output:
avals
------------------------------------------------------
{George,NULL,Harrison}
{John,Winston,Lennon}
{Paul,"",McCartney}
{Ringo,"my passions are ring,drum and shades",Starr}
(4 rows)
Just use avals
ツ
Live test: http://www.sqlfiddle.com/#!1/d41d8/388
Please do note that although sqlfiddle output don't have an array indicator(curly brackets) and double quotes on "my passions are ring,drum and shades", the avals result is an array and the string with comma in them has double quote in actual results, you can test it on your pgAdmin or psql
Might be this: http://www.sqlfiddle.com/#!1/d41d8/364
select translate(string_to_array(x.*::text,',')::text,'()','')::text[]
from pg_tables as x
How it works (inside-out), 5 steps:
1st:
select x.*::text from pg_tables as x;
Sample Output:
| X |
----------------------------------------------------------------
| (pg_catalog,pg_statistic,postgres,,t,f,f) |
| (pg_catalog,pg_type,postgres,,t,f,f) |
2nd:
select string_to_array(x.*::text,',') from pg_tables as x;
Sample Output:
| STRING_TO_ARRAY |
---------------------------------------------
| (pg_catalog,pg_statistic,postgres,,t,f,f) |
| (pg_catalog,pg_type,postgres,,t,f,f) |
3rd:
select string_to_array(x.*::text,',')::text from pg_tables as x;
Sample Output:
| STRING_TO_ARRAY |
-------------------------------------------------
| {(pg_catalog,pg_statistic,postgres,"",t,f,f)} |
| {(pg_catalog,pg_type,postgres,"",t,f,f)} |
4th:
select translate( string_to_array(x.*::text,',')::text, '()', '') from pg_tables as x
Sample Output:
| TRANSLATE |
-----------------------------------------------
| {pg_catalog,pg_statistic,postgres,"",t,f,f} |
| {pg_catalog,pg_type,postgres,"",t,f,f} |
Finally:
select translate( string_to_array(x.*::text,',')::text, '()', '')::text[]
from pg_tables as x
Sample Output:
| TRANSLATE |
-------------------------------------------
| pg_catalog,pg_statistic,postgres,,t,f,f |
| pg_catalog,pg_type,postgres,,t,f,f |
Live test: http://www.sqlfiddle.com/#!1/d41d8/373
To prove that it works:
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;
Sample output:
| 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 |
This function works with all corner cases including NULL
values, empty strings or special characters in the values.
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;
Call:
SELECT * FROM f_rows_to_arr ('mytbl');
The cast to regclass avoids SQLi. Columns are not sorted in this version. More explanation for used techniques and links in this related answer.