Postgresql - return entire row as array

前端 未结 4 2194
南方客
南方客 2021-02-09 17:32

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

4条回答
  •  离开以前
    2021-02-09 18:00

    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

提交回复
热议问题