繁体   English   中英

如何获取PostgreSQL表中所有索引的列名列表?

[英]How to get the list of column names for all indexes on a table in PostgreSQL?

我有此查询以获取表上的索引列表:

SELECT
    ns.nspname as schema_name,
    tab.relname as table_name,
    cls.relname as index_name,
    am.amname as index_type,
    idx.indisprimary as is_primary,
    idx.indisunique as is_unique
FROM
    pg_index idx
INNER JOIN pg_class cls ON cls.oid=idx.indexrelid
INNER JOIN pg_class tab ON tab.oid=idx.indrelid
INNER JOIN pg_am am ON am.oid=cls.relam
INNER JOIN pg_namespace ns on ns.oid=tab.relnamespace
WHERE ns.nspname = @Schema AND tab.relname = @Name

它似乎工作正常。 但是现在我需要查询列列表,并且在理解系统视图的工作方式时遇到了麻烦。

具体来说,我正在寻找的是:

  • [用于匹配第一个查询的索引名称或ID]
  • 索引顺序
  • 栏名
  • 上升或下降
  • 排序列或包含列

理想情况下,我希望一次获得给定表的所有索引的上述项目。


请注意,我不仅在寻找列名。

使用系统目录信息功能pg_get_indexdef(index_oid)获取完整的信息(包括索引表达式列表)-在针对pg_index的查询中获取给定表的所有索引:

SELECT pg_get_indexdef(indexrelid) || ';' AS idx
FROM   pg_index
WHERE  indrelid = 'public.tbl'::regclass;  -- optionally schema-qualified

有关:

如果您使用不合格的表名(无模式),则取决于当前的search_path设置,并且可能会在其他模式中获得同名表的结果。

或者 ,您可以手动加入pg_attribute以获得各个列,如以下相关答案所示:

关键要素是这样加入:

FROM   pg_index idx
LEFT   JOIN pg_attribute a ON a.attrelid = idx.indrelid
                          AND a.attnum = ANY(idx.indkey)
                          AND a.attnum > 0

关于pg_index.indkey的手册:

这是indnatts值的数组,它们指示此索引索引的表列。 例如,值1 3表示第一和第三表列构成索引条目。 关键列位于非关键(包含)列之前。 此数组中的零表示相应的索引属性是表列上的表达式,而不是简单的列引用。

从技术上讲,不需要AND a.attnum > 0因为没有a.attnum = 0 但这使查询更清晰,不会受到伤害。 手册:

普通列从1开始编号。 系统列(例如oid)具有(任意)负数。

请注意, “列名列表”实际上也可以包含表达式。 而且自Postgres 11起,也有“ included”列(那里没有表达式)。 pg_get_indexdef()处理所有可能的复杂情况。

您可以从系统目录中一起困惑它,如Erwin Brandstetter所详述。

这是一个查询,它将返回您想要的信息:

SELECT i.indexrelid::regclass AS indexname,                                    
       k.i AS index_order,                                                     
       i.indnkeyatts,                                                          
       coalesce(a.attname,                                                     
                (('{' || pg_get_expr(                                          
                            i.indexprs,                                        
                            i.indrelid                                         
                         )                                                     
                      || '}')::text[]                                          
                )[k.i]                                                         
               ) AS index_column,                                              
       i.indoption[k.i - 1] = 0 AS ascending,                                  
       k.i <= i.indnkeyatts AS is_key                                          
FROM pg_index i                                                                
   CROSS JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS k(attnum, i)         
   LEFT JOIN pg_attribute AS a                                                 
      ON i.indrelid = a.attrelid AND k.attnum = a.attnum                       
WHERE i.indrelid = 'schemaname.tablename'::regclass;

该查询仅适用于PostgreSQL v11及更高版本(但v11之前没有涵盖的索引)。

另外,如果索引表达式包含逗号,查询将失败;否则,查询将失败。 我不知道该如何解决。

版本10.4

SELECT idx.indexrelid::regclass AS indexname,                                    
       k.i AS index_order,                                                     
       --i.indnkeyatts,                                                          
       coalesce(att.attname,                                                     
                (('{' || pg_get_expr(                                          
                            idx.indexprs,                                        
                            idx.indrelid                                         
                         )                                                     
                      || '}')::text[]                                          
                )[k.i]                                                         
               ) AS index_column,                                              
       pg_index_column_has_property(idx.indexrelid,k.i::int,'asc') AS ascending,                                  
       k.i != -1 AS is_key                                          
FROM pg_index idx                                                                
   CROSS JOIN LATERAL unnest(idx.indkey) WITH ORDINALITY AS k(attnum, i)         
   LEFT JOIN pg_attribute AS att                                                 
      ON idx.indrelid = att.attrelid AND k.attnum = att.attnum  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM