我有这个查询来获取表上的索引列表:
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
似乎工作正常。但是现在我需要查询列列表,并且在理解系统视图的工作方式时遇到了麻烦。
我要寻找的是:
理想情况下,我希望一次获得给定表的所有索引的上述项目。
请注意,我不仅在寻找列名。
答案 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