首页 > 解决方案 > postgres:列出所有具有唯一索引的列名

问题描述

我需要列出表的所有列名并显示它是否应用了唯一索引。我可以显示每个表/模式的所有唯一索引,但不能显示每列。这是我的结局:

select 
    ns.nspname as schema, 
    idx.indrelid :: REGCLASS as table_name, 
    idx.indisunique as indu, 
    i.relname from pg_index as idx 
  join pg_class as i on i.oid = idx.indexrelid 
  join pg_namespace as ns on i.relnamespace = ns.oid 
where NOT ns.nspname like 'pg%';

标签: sqlpostgresql

解决方案


我没有用于测试的 PostgreSQL 11 数据库,所以我不太确定是否没有错误,但看看这个(你可以选择省略WHERE,但我猜系统列可能与你无关不包括oid):

SELECT
    n.nspname,
    c.relname,
    a.attname,
    (i.indisunique IS TRUE) AS part_of_unique_index
FROM pg_class c
    INNER JOIN pg_namespace n ON n.oid = c.relnamespace
    INNER JOIN pg_attribute a ON a.attrelid = c.oid
    LEFT JOIN pg_index i 
        ON i.indrelid = c.oid 
            AND a.attnum = ANY (i.indkey[0:(i.indnkeyatts - 1)])
WHERE a.attnum > 0;

注意INCLUDE对于 PostgreSQL 11 中的索引是新的。如果您使用的是较低版本,请使用以下内容(如果您还想查看 PostgreSQL 11 中的非键列,也可以使用它):

SELECT
    n.nspname,
    c.relname,
    a.attname,
    (i.indisunique IS TRUE) AS part_of_unique_index
FROM pg_class c
    INNER JOIN pg_namespace n ON n.oid = c.relnamespace
    INNER JOIN pg_attribute a ON a.attrelid = c.oid
    LEFT JOIN pg_index i 
        ON i.indrelid = c.oid AND a.attnum = ANY (i.indkey)
WHERE a.attnum > 0;

注意2:这个答案已经过编辑,说indnkeyatts是错误的字段,你应该indnatts改用。我不同意这一点,因为这意味着仅在INCLUDE唯一索引的一部分中的列也将被标记为对其应用了唯一约束。但实际上,它们只是存储在索引中,而不必唯一的。所以我认为对于原始海报,indnkeyatts是要走的路。如果您还想只查看包含的列,请使用indnatts.


推荐阅读