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

Jon*_*len 3 postgresql database-metadata database-indexes

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

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
Run Code Online (Sandbox Code Playgroud)

它似乎工作正常。但现在我需要对列列表进行查询,但我无法理解系统视图的工作方式。

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

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

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


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

Erw*_*ter 6

使用系统目录信息函数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
Run Code Online (Sandbox Code Playgroud)

有关的:

如果您依赖非限定的表名(没有架构),则您依赖于当前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
Run Code Online (Sandbox Code Playgroud)

手册关于pg_index.indkey

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

添加AND a.attnum > 0在技​​术上不是必需的,因为没有a.attnum = 0. 但它使查询更清晰,它不会受到伤害。手册:

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

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

  • @JonathanAllen:Oracle、DB2 和某些 Firebird 也支持在表达式上创建索引。这并不是 Postgres 独有的 (2认同)