6

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

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

4 回答 4

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 |
于 2012-07-13T11:48:41.087 回答
6

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

添加hstorecontrib 类型,执行一次:

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ツ</p>

现场测试http ://www.sqlfiddle.com/#!1/d41d8/388

请注意,虽然 sqlfiddle 输出没有数组指示符(大括号)和“我的激情是戒指,鼓和阴影”上的双引号,但 avals 结果是一个数组,其中带有逗号的字符串有双引号实际结果,您可以在 pgAdmin 或 psql 上对其进行测试

于 2012-07-13T14:44:20.270 回答
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。此版本中未对列进行排序。此相关答案中使用的技术和链接的更多解释。

于 2012-07-13T18:22:36.330 回答
0

string_to_array 可能会有所帮助:

SELECT string_to_array(pg_tables::text,','::text) FROM pg_tables;
于 2012-07-13T11:04:42.920 回答