如何获取数据库中所有表中每个TEXT字段的最大字段值长度

Bri*_*ian 4 postgresql dynamic-sql plpgsql

我正在尝试获取有关数据库中数据的信息。我在几个表中有几列输入“TEXT”。我想执行一个查询,该查询将创建如下所示的结果:

|table_name|column_name|max_length|
-----------------------------------
|my_table  |name       |35        |
Run Code Online (Sandbox Code Playgroud)

我有查询来获取所有表和列:

SELECT table_name, column_name FROM information_schema.columns
WHERE table_schema = 'public' AND data_type = 'text'
ORDER BY table_name
Run Code Online (Sandbox Code Playgroud)

但我现在不知道如何遍历每个表和列以获得每列的最大长度。我确实有一个查询来获取特定列和表的最大长度:

SELECT 'my_table', 'name', MAX(LENGTH(name)) FROM my_table
Run Code Online (Sandbox Code Playgroud)

如何进行查询,根据查询结果动态获取最大长度以获取所有表和列?

小智 8

不需要 PL/pgSQL。

您可以使用此解决方案的变体在单个查询中完成所有操作。

select table_schema, 
       table_name,
       column_name, 
       (xpath('/row/max/text()',query_to_xml(format('select max(length(%I)) from %I.%I', column_name, table_schema, table_name), true, true, '')))[1]::text::int as max_length
from information_schema.columns
where table_schema = 'public'       
  and data_type = 'text'
order by table_schema, table_name, column_name;
Run Code Online (Sandbox Code Playgroud)

埃文的评论让我思考是否有一种方法可以使用每个表的单个语句来完成此操作(尽管我怀疑这种性能优化对于“获取有关数据库查询的一些信息”是否真的很重要)

通过一些 XML 处理,这确实是可能的:

with counts as (
  select table_schema, 
         table_name,
         query_to_xml(format('select %s from %I.%I', string_agg(format('max(length(%I)) as %I', column_name, column_name), ', '), table_schema, table_name), 
                      true, true, '') as result
  from information_schema.columns
  where table_schema = 'public'       
    and data_type = 'text'
  group by table_schema, table_name
)
select table_schema, 
       table_name, 
       substring(x::text, 2, strpos(x::text,'>') - 2) as column_name,
       (xpath('./text()', x))[1]::text::int as max_length
from counts, unnest(xpath('//row/*', result)) as c(x);
Run Code Online (Sandbox Code Playgroud)

对于 pagila 演示数据库,返回:

select table_schema, 
       table_name,
       column_name, 
       (xpath('/row/max/text()',query_to_xml(format('select max(length(%I)) from %I.%I', column_name, table_schema, table_name), true, true, '')))[1]::text::int as max_length
from information_schema.columns
where table_schema = 'public'       
  and data_type = 'text'
order by table_schema, table_name, column_name;
Run Code Online (Sandbox Code Playgroud)

上面首先为每个表生成一个语句,其中max(length(..))每列都有一个语句。

然后,结果被解析并再次转换为行。可以将其聚合回单个 JSON。


要获取每个表一行,并将列信息作为 JSON 值,可以使用以下命令:

with counts as (
  select table_schema, 
         table_name,
         query_to_xml(format('select to_jsonb(t) as cols from (select %s from %I.%I) t', string_agg(format('max(length(%I)) as %I', column_name, column_name), ', '), table_schema, table_name), 
                      false, true, '') as result
  from information_schema.columns
  where table_schema = 'public'       
    and data_type = 'text'
  group by table_schema, table_name
)
select table_schema, 
       table_name, 
       (xpath('//row/cols/text()', result))[1]::text::jsonb as column_sizes
from counts;
Run Code Online (Sandbox Code Playgroud)

对于 pagila 演示数据库,返回:

with counts as (
  select table_schema, 
         table_name,
         query_to_xml(format('select %s from %I.%I', string_agg(format('max(length(%I)) as %I', column_name, column_name), ', '), table_schema, table_name), 
                      true, true, '') as result
  from information_schema.columns
  where table_schema = 'public'       
    and data_type = 'text'
  group by table_schema, table_name
)
select table_schema, 
       table_name, 
       substring(x::text, 2, strpos(x::text,'>') - 2) as column_name,
       (xpath('./text()', x))[1]::text::int as max_length
from counts, unnest(xpath('//row/*', result)) as c(x);
Run Code Online (Sandbox Code Playgroud)