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

时间:2019-04-01 03:37:57

标签: postgresql database-indexes database-metadata

我有这个查询来获取表上的索引列表:

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]
  • 索引中的顺序
  • 列名
  • 上升或下降
  • 排序列或包含列

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


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

3 个答案:

答案 0 :(得分:3)

使用系统目录信息功能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的值表示   第一和第三表列构成索引条目。键   列在非关键(包含)列之前。该数组中的零   指示相应的index属性是一个表达式   表列,而不是简单的列引用。

由于没有AND a.attnum > 0,因此从技术上讲,不需要添加a.attnum = 0。但这使查询更清晰,不会受到伤害。 The manual:

  

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

请注意,“列名列表” 实际上也可以包含表达式。而且自Postgres 11起,也有“ included”列(那里没有表达式)。 pg_get_indexdef()开箱即用地处理所有可能的并发症。

答案 1 :(得分:1)

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

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

Super+D

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

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

答案 2 :(得分:0)

版本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