PostgreSQL - 从数据库表

时间:2018-03-09 19:35:28

标签: postgresql

我想知道是否可以使用单个PostgreSQL查询从数据库表中提取列名,数据类型和一个样本值。我的目标是为一个表的所有列执行此操作。

列名称需要感觉像变量一样,因此您可以在查询表中查找示例值时使用它,但Postgres在纯SQL语句(How to declare a variable in a PostgreSQL query)中不支持此功能。

我可以通过对单个值进行硬编码来实现这一点,但是对于是否可以对表的每一列进行任何建议(在select语句中使用其名称连接每个值以获取单个样本值)?

column   | data_type | sample_val
--------------------------------
foo_col1 |   text    | NULL
foo_col2 |   text    | 'foo_val2'
foo_col3 |   text    | NULL
select column_name as column, data_type, sample_val
from information_schema.columns t1
join pg_class t2 on (t1.table_name = t2.relname)
left outer join pg_description t3 on (t2.oid = t3.objoid and t3.objsubid = t1.ordinal_position)

left outer join (select CAST('foo_col2' AS text) as foo_col2, foo_col2 as sample_val from foo_schema.foo_table limit 1) n2
on (n2.foo_col2 = column_name)

where table_schema = 'foo_schema'
and table_name = 'foo_table'
order by ordinal_position

1 个答案:

答案 0 :(得分:0)

您可以使用row count for all tables的变体:

select c.table_schema, c.table_name,
       c.column_name,
       c.data_type,
       (xpath('/table/row/'||column_name||'/text()', 
          query_to_xml(format('select %I 
                               from %I.%I limit 1', c.column_name, c.table_schema, c.table_name), true, false, '')))[1]::text as sample_value
from information_schema.columns c 
where table_schema = 'foo_schema';

query_to_xml()将运行查询并将结果格式化为XML。然后xpath()函数从XML中提取该列值。

这非常昂贵,因为每个列运行一次查询,而不是每个表运行一次。请注意,示例值可能不是来自同一行。

您可以通过每个表运行一个查询然后将该结果连接回列来优化它:

with samples as (
  select table_schema, 
         table_name, 
         query_to_xml(format('select * from %I.%I limit 1', table_schema, table_name), true, false, '') as sample_row
  from information_schema.tables 
  where table_schema = 'foo_schema'
)
select c.table_schema, c.table_name,
       c.column_name,
       c.data_type,
       (xpath('/table/row/'||column_name||'/text()', s.sample_row))[1]::text as sample_value
from information_schema.columns c 
  join samples s on (s.table_schema, s.table_name) = (c.table_schema, c.table_name);

使用上述内容,所有样本值都来自同一行。