关于sql:列出PostgreSQL中带索引的列

List columns with indexes in PostgreSQL

我想获得PostgreSQL中索引所在的列。

在MySQL中,您可以使用SHOW INDEXES FOR table并查看Column_name列。

1
2
3
4
5
6
7
8
9
mysql> SHOW indexes FROM foos;

+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| TABLE | Non_unique | Key_name            | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | NULL | Index_type | Comment |
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| foos  |          0 | PRIMARY             |            1 | id          | A         |       19710 |     NULL | NULL   |      | BTREE      |         |
| foos  |          0 | index_foos_on_email |            1 | email       | A         |       19710 |     NULL | NULL   | YES  | BTREE      |         |
| foos  |          1 | index_foos_on_name  |            1 | name        | A         |       19710 |     NULL | NULL   |      | BTREE      |         |
+-------+------------+---------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+

PostgreSQL有这样的东西吗?

我在psql命令提示符处尝试了\d(使用-E选项来显示SQL),但它没有显示我正在寻找的信息。

更新:感谢所有添加了答案的人。 cope360给了我正是我想要的东西,但有几个人用非常有用的链接插话。 为了将来参考,请查看pg_index(通过Milen A. Radev)的文档和非常有用的文章从PostgreSQL中提取META信息(通过Micha?Niklas)。


创建一些测试数据......

1
2
3
CREATE TABLE test (a INT, b INT, c INT, CONSTRAINT pk_test PRIMARY KEY(a, b));
CREATE TABLE test2 (a INT, b INT, c INT, CONSTRAINT uk_test2 UNIQUE (b, c));
CREATE TABLE test3 (a INT, b INT, c INT, CONSTRAINT uk_test3b UNIQUE (b), CONSTRAINT uk_test3c UNIQUE (c),CONSTRAINT uk_test3ab UNIQUE (a, b));

列出索引的索引和列:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
SELECT
    t.relname AS TABLE_NAME,
    i.relname AS index_name,
    a.attname AS column_name
FROM
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
WHERE
    t.oid = ix.indrelid
    AND i.oid = ix.indexrelid
    AND a.attrelid = t.oid
    AND a.attnum = ANY(ix.indkey)
    AND t.relkind = 'r'
    AND t.relname LIKE 'test%'
ORDER BY
    t.relname,
    i.relname;

 TABLE_NAME | index_name | column_name
------------+------------+-------------
 test       | pk_test    | a
 test       | pk_test    | b
 test2      | uk_test2   | b
 test2      | uk_test2   | c
 test3      | uk_test3ab | a
 test3      | uk_test3ab | b
 test3      | uk_test3b  | b
 test3      | uk_test3c  | c

汇总列名:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
SELECT
    t.relname AS TABLE_NAME,
    i.relname AS index_name,
    array_to_string(array_agg(a.attname), ', ') AS column_names
FROM
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
WHERE
    t.oid = ix.indrelid
    AND i.oid = ix.indexrelid
    AND a.attrelid = t.oid
    AND a.attnum = ANY(ix.indkey)
    AND t.relkind = 'r'
    AND t.relname LIKE 'test%'
GROUP BY
    t.relname,
    i.relname
ORDER BY
    t.relname,
    i.relname;

 TABLE_NAME | index_name | column_names
------------+------------+--------------
 test       | pk_test    | a, b
 test2      | uk_test2   | b, c
 test3      | uk_test3ab | a, b
 test3      | uk_test3b  | b
 test3      | uk_test3c  | c


\d table_name显示来自psql的此信息,但如果您想使用SQL从数据库获取此类信息,请查看从PostgreSQL中提取META信息。

我在我的实用程序中使用这样的信息来报告来自db模式的一些信息,以比较测试和生产环境中的PostgreSQL数据库。


PostgreSQL(pg_indexes):

1
SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL(SHOW INDEX):

1
SHOW INDEX FROM mytable;


只需:\d table_name

但我不确定你的意思是关于列的信息不存在。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# \d pg_class
       TABLE"pg_catalog.pg_class"
     COLUMN      |   TYPE    | Modifiers
-----------------+-----------+-----------
 relname         | name      | NOT NULL
 relnamespace    | oid       | NOT NULL
 reltype         | oid       | NOT NULL
 reloftype       | oid       | NOT NULL
 relowner        | oid       | NOT NULL
 relam           | oid       | NOT NULL
 relfilenode     | oid       | NOT NULL
 reltablespace   | oid       | NOT NULL
 relpages        | INTEGER   | NOT NULL
 reltuples       | REAL      | NOT NULL
 reltoastrelid   | oid       | NOT NULL
 reltoastidxid   | oid       | NOT NULL
 relhasindex     | BOOLEAN   | NOT NULL
 relisshared     | BOOLEAN   | NOT NULL
 relistemp       | BOOLEAN   | NOT NULL
 relkind         |"char"    | NOT NULL
 relnatts        | SMALLINT  | NOT NULL
 relchecks       | SMALLINT  | NOT NULL
 relhasoids      | BOOLEAN   | NOT NULL
 relhaspkey      | BOOLEAN   | NOT NULL
 relhasexclusion | BOOLEAN   | NOT NULL
 relhasrules     | BOOLEAN   | NOT NULL
 relhastriggers  | BOOLEAN   | NOT NULL
 relhassubclass  | BOOLEAN   | NOT NULL
 relfrozenxid    | xid       | NOT NULL
 relacl          | aclitem[] |
 reloptions      | text[]    |
Indexes:
   "pg_class_oid_index" UNIQUE, btree (oid)
   "pg_class_relname_nsp_index" UNIQUE, btree (relname, relnamespace)

它清楚地显示了给定索引的列在此表上。


# \di

简单和最短的方法是\di,它将列出当前数据库中的所有索引。

1
2
3
4
5
6
7
8
9
10
$ \di
                      List OF relations
 Schema |            Name             | TYPE  |  Owner   |     TABLE    
--------+-----------------------------+-------+----------+---------------
 public | part_delivery_index         | INDEX | shipper  | part_delivery
 public | part_delivery_pkey          | INDEX | shipper  | part_delivery
 public | shipment_by_mandator        | INDEX | shipper  | shipment_info
 public | shipment_by_number_and_size | INDEX | shipper  | shipment_info
 public | shipment_info_pkey          | INDEX | shipper  | shipment_info
(5 ROWS)

\di\d命令的"小兄弟",它将列出当前数据库的所有关系。因此\di当然代表"向我展示这个数据库索引"。

键入\diS将列出系统范围内使用的所有索引,这意味着您也可以获得所有pg_catalog索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ \diS
                                      List OF relations
   Schema   |                   Name                    | TYPE  |  Owner   |          TABLE
------------+-------------------------------------------+-------+----------+-------------------------
 pg_catalog | pg_aggregate_fnoid_index                  | INDEX | postgres | pg_aggregate
 pg_catalog | pg_am_name_index                          | INDEX | postgres | pg_am
 pg_catalog | pg_am_oid_index                           | INDEX | postgres | pg_am
 pg_catalog | pg_amop_fam_strat_index                   | INDEX | postgres | pg_amop
 pg_catalog | pg_amop_oid_index                         | INDEX | postgres | pg_amop
 pg_catalog | pg_amop_opr_fam_index                     | INDEX | postgres | pg_amop
 pg_catalog | pg_amproc_fam_proc_index                  | INDEX | postgres | pg_amproc
 pg_catalog | pg_amproc_oid_index                       | INDEX | postgres | pg_amproc
 pg_catalog | pg_attrdef_adrelid_adnum_index            | INDEX | postgres | pg_attrdef
--More--

使用这两个命令,您可以在其后添加+以获取更多信息,例如索引所需的磁盘空间大小和可用的描述。

1
2
3
4
5
6
7
8
9
10
$ \di+
                                 List OF relations
 Schema |            Name             | TYPE  |  Owner   |     TABLE     | SIZE  | Description
--------+-----------------------------+-------+----------+---------------+-------+-------------
 public | part_delivery_index         | INDEX | shipper  | part_delivery | 16 kB |
 public | part_delivery_pkey          | INDEX | shipper  | part_delivery | 16 kB |
 public | shipment_by_mandator        | INDEX | shipper  | shipment_info | 19 MB |
 public | shipment_by_number_and_size | INDEX | shipper  | shipment_info | 19 MB |
 public | shipment_info_pkey          | INDEX | shipper  | shipment_info | 53 MB |
(5 ROWS)

在psql中,您可以轻松找到有关键入\?的命令的帮助。


结合其他代码并创建一个视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
CREATE OR REPLACE VIEW view_index AS
SELECT
     n.nspname  AS"schema"
    ,t.relname  AS"table"
    ,c.relname  AS"index"
    ,pg_get_indexdef(indexrelid) AS"def"
FROM pg_catalog.pg_class c
    JOIN pg_catalog.pg_namespace n ON n.oid        = c.relnamespace
    JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
    JOIN pg_catalog.pg_class t ON i.indrelid   = t.oid
WHERE c.relkind = 'i'
    AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
    AND pg_catalog.pg_table_is_visible(c.oid)
ORDER BY
     n.nspname
    ,t.relname
    ,c.relname;

一些样本数据......

1
2
3
CREATE TABLE test (a INT, b INT, c INT, CONSTRAINT pk_test PRIMARY KEY(a, b));
CREATE TABLE test2 (a INT, b INT, c INT, CONSTRAINT uk_test2 UNIQUE (b, c));
CREATE TABLE test3 (a INT, b INT, c INT, CONSTRAINT uk_test3b UNIQUE (b), CONSTRAINT uk_test3c UNIQUE (c), CONSTRAINT uk_test3ab UNIQUE (a, b));

使用pg_get_indexdef功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid = 'test'::regclass;

                    pg_get_indexdef
--------------------------------------------------------
 CREATE UNIQUE INDEX pk_test ON test USING btree (a, b)
(1 ROW)


SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid = 'test2'::regclass;
                     pg_get_indexdef
----------------------------------------------------------
 CREATE UNIQUE INDEX uk_test2 ON test2 USING btree (b, c)
(1 ROW)


SELECT pg_get_indexdef(indexrelid) FROM pg_index WHERE indrelid ='test3'::regclass;
                      pg_get_indexdef
------------------------------------------------------------
 CREATE UNIQUE INDEX uk_test3b ON test3 USING btree (b)
 CREATE UNIQUE INDEX uk_test3c ON test3 USING btree (c)
 CREATE UNIQUE INDEX uk_test3ab ON test3 USING btree (a, b)
(3 ROWS)


此命令也显示表变量,索引和约束的视图

1
=# \d TABLE_NAME;

例:

1
testannie=# \d dv.l_customer_account;

\d tablename在版本8.3.8上显示了我的列名。

1
"username_idx" UNIQUE, btree (username), tablespace"alldata1"


查询结果:

1
2
3
4
5
6
TABLE |     COLUMN     |          TYPE          | notnull |  index_name  | is_index | primarykey | uniquekey | DEFAULT
-------+----------------+------------------------+---------+--------------+----------+-   -----------+-----------+---------
 nodes | dns_datacenter | CHARACTER VARYING(255) | f       |              | f        | f          | f         |
 nodes | dns_name       | CHARACTER VARYING(255) | f       | dns_name_idx | t        | f          | f         |
 nodes | id             | uuid                   | t       | nodes_pkey   | t        | t          | t         |
(3 ROWS)

查询:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
SELECT  
c.relname AS TABLE,
f.attname AS COLUMN,  
pg_catalog.format_type(f.atttypid,f.atttypmod) AS TYPE,
f.attnotnull AS notnull,  
i.relname AS index_name,
CASE  
    WHEN i.oid<>0 THEN 't'  
    ELSE 'f'  
END AS is_index,  
CASE  
    WHEN p.contype = 'p' THEN 't'  
    ELSE 'f'  
END AS primarykey,  
CASE  
    WHEN p.contype = 'u' THEN 't'
    WHEN p.contype = 'p' THEN 't'
    ELSE 'f'
END AS uniquekey,
CASE
    WHEN f.atthasdef = 't' THEN d.adsrc
END AS DEFAULT  FROM pg_attribute f  
JOIN pg_class c ON c.oid = f.attrelid  
JOIN pg_type t ON t.oid = f.atttypid  
LEFT JOIN pg_attrdef d ON d.adrelid = c.oid AND d.adnum = f.attnum  
LEFT JOIN pg_namespace n ON n.oid = c.relnamespace  
LEFT JOIN pg_constraint p ON p.conrelid = c.oid AND f.attnum = ANY (p.conkey)  
LEFT JOIN pg_class AS g ON p.confrelid = g.oid
LEFT JOIN pg_index AS ix ON f.attnum = ANY(ix.indkey) AND c.oid = f.attrelid AND c.oid = ix.indrelid
LEFT JOIN pg_class AS i ON ix.indexrelid = i.oid

WHERE c.relkind = 'r'::CHAR  
AND n.nspname = 'public'  -- Replace with Schema name
--AND c.relname = 'nodes'  -- Replace with table name, or Comment this for get all tables
AND f.attnum > 0
ORDER BY c.relname,f.attname;


原始信息位于pg_index中。


如果你想保留索引中的列顺序,这是一种(非常难看)的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SELECT TABLE_NAME,
    index_name,
    array_agg(column_name)
FROM (
    SELECT
        t.relname AS TABLE_NAME,
        i.relname AS index_name,
        a.attname AS column_name,
        unnest(ix.indkey) AS unn,
        a.attnum
    FROM
        pg_class t,
        pg_class i,
        pg_index ix,
        pg_attribute a
    WHERE
        t.oid = ix.indrelid
        AND i.oid = ix.indexrelid
        AND a.attrelid = t.oid
        AND a.attnum = ANY(ix.indkey)
        AND t.relkind = 'r'
        AND t.relnamespace = <oid OF the schema you're interested in>
    order by
        t.relname,
        i.relname,
        generate_subscripts(ix.indkey,1)) sb
where unn = attnum
group by table_name, index_name

列顺序存储在pg_index.indkey列中,因此我按该数组的下标排序。


在使用索引时,索引中构造列的顺序与列本身一样重要。

以下查询以排序方式列出给定表及其所有列的所有索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
SELECT
  TABLE_NAME,
  index_name,
  string_agg(column_name, ',')
FROM (
       SELECT
         t.relname AS TABLE_NAME,
         i.relname AS index_name,
         a.attname AS column_name,
         (SELECT i
          FROM (SELECT
                  *,
                  ROW_NUMBER()
                  OVER () i
                FROM unnest(indkey) WITH ORDINALITY AS a(v)) a
          WHERE v = attnum)
       FROM
         pg_class t,
         pg_class i,
         pg_index ix,
         pg_attribute a
       WHERE
         t.oid = ix.indrelid
         AND i.oid = ix.indexrelid
         AND a.attrelid = t.oid
         AND a.attnum = ANY (ix.indkey)
         AND t.relkind = 'r'
         AND t.relname LIKE 'tablename'
       ORDER BY TABLE_NAME, index_name, i
     ) raw
GROUP BY TABLE_NAME, index_name


Similar to the accepted answer but having left join on pg_attribute as normal join or query with pg_attribute doesnt give indices which are like :
create unique index unique_user_name_index on users (lower(name))

1
2
3
4
5
6
7
8
9
10
SELECT
    ROW_NUMBER() OVER (ORDER BY c.relname),
    c.relname AS INDEX,
    t.relname AS TABLE,
    array_to_string(array_agg(a.attname), ', ') AS column_names
FROM pg_class c
JOIN pg_index i ON c.oid = i.indexrelid AND c.relkind='i' AND c.relname NOT LIKE 'pg_%'
JOIN pg_class t ON t.oid = i.indrelid
LEFT JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)
GROUP BY t.relname, c.relname ORDER BY c.relname;


这是一个包含cope360答案的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
CREATE OR REPLACE FUNCTION getIndices(_table_name VARCHAR)
  RETURNS TABLE(TABLE_NAME VARCHAR, index_name VARCHAR, column_name VARCHAR) AS $$
  BEGIN
    RETURN QUERY
    SELECT
    t.relname::VARCHAR AS TABLE_NAME,
    i.relname::VARCHAR AS index_name,
    a.attname::VARCHAR AS column_name
FROM
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
WHERE
    t.oid = ix.indrelid
    AND i.oid = ix.indexrelid
    AND a.attrelid = t.oid
    AND a.attnum = ANY(ix.indkey)
    AND t.relkind = 'r'
    AND t.relname = _table_name
ORDER BY
    t.relname,
    i.relname;
  END;
  $$ LANGUAGE plpgsql;

用法:

1
SELECT * FROM getIndices('<my_table>')


请尝试以下查询以深入查看所需的索引

Query as below -- i have tried this personally and use it frequently.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT n.nspname AS"Schema",
  c.relname AS"Name",
  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'i'
THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' END AS"Type",
  u.usename AS"Owner",
 c2.relname AS"Table"
FROM pg_catalog.pg_class c
     JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
     JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid
     LEFT JOIN pg_catalog.pg_user u ON u.usesysid = c.relowner
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind IN ('i','')
      AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
      AND pg_catalog.pg_table_is_visible(c.oid)
      AND c2.relname LIKE '%agg_transaction%' --table name
      AND nspname = 'edjus' -- schema name
ORDER BY 1,2;

一个简单的解决方案如何:

1
2
3
4
5
6
7
8
9
10
SELECT
  t.relname TABLE_NAME,
  ix.relname index_name,
  indisunique,
  indisprimary,
  regexp_replace(pg_get_indexdef(indexrelid), '.*\((.*)\)', '\1') COLUMNS
FROM pg_index i
JOIN pg_class t ON t.oid = i.indrelid
JOIN pg_class ix ON ix.oid = i.indexrelid
WHERE t.relname LIKE 'test%'

`


@ cope360接受的答案很好,但我想要更像Oracle的DBA_IND_COLUMNS,ALL_IND_COLUMNS和USER_IND_COLUMNS(例如,报告表/索引架构和索引在多列索引中的位置),所以我改编了接受回答这个问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
WITH
 ind_cols AS (
SELECT
    n.nspname AS schema_name,
    t.relname AS TABLE_NAME,
    i.relname AS index_name,
    a.attname AS column_name,
    1 + array_position(ix.indkey, a.attnum) AS column_position
FROM
     pg_catalog.pg_class t
JOIN pg_catalog.pg_attribute a ON t.oid    =      a.attrelid
JOIN pg_catalog.pg_index ix    ON t.oid    =     ix.indrelid
JOIN pg_catalog.pg_class i     ON a.attnum = any(ix.indkey)
                              AND i.oid    =     ix.indexrelid
JOIN pg_catalog.pg_namespace n ON n.oid    =      t.relnamespace
WHERE t.relkind = 'r'
ORDER BY
    t.relname,
    i.relname,
    array_position(ix.indkey, a.attnum)
)
SELECT *
FROM ind_cols
WHERE schema_name = 'test'
  AND TABLE_NAME  = 'indextest'
ORDER BY schema_name, TABLE_NAME
;

这给出了如下输出:

1
2
3
4
5
6
 schema_name | TABLE_NAME | index_name | column_name | column_position
-------------+------------+------------+-------------+-----------------
 test        | indextest  | testind1   | singleindex |               1
 test        | indextest  | testind2   | firstoftwo  |               1
 test        | indextest  | testind2   | secondoftwo |               2
(3 ROWS)

@ cope360的优秀答案,转换为使用连接语法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
SELECT t.relname AS TABLE_NAME
     , i.relname AS index_name
     , array_to_string(array_agg(a.attname), ', ') AS column_names
FROM pg_class t
JOIN pg_index ix
ON t.oid = ix.indrelid
JOIN pg_class i
ON i.oid = ix.indexrelid
JOIN pg_attribute a
ON a.attrelid = t.oid
AND a.attnum = ANY(ix.indkey)
WHERE t.relkind = 'r'
AND t.relname LIKE 'test%'
GROUP BY t.relname
       , i.relname
ORDER BY t.relname
       , i.relname
;


我不认为这个版本存在此版本:它提供了列名列表以及索引的ddl。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CREATE OR REPLACE VIEW V_TABLE_INDEXES AS

SELECT
     n.nspname  AS"schema"
    ,t.relname  AS"table"
    ,c.relname  AS"index"
    ,i.indisunique AS"is_unique"
    ,array_to_string(array_agg(a.attname), ', ') AS"columns"
    ,pg_get_indexdef(i.indexrelid) AS"ddl"
FROM pg_catalog.pg_class c
    JOIN pg_catalog.pg_namespace n ON n.oid        = c.relnamespace
    JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid
    JOIN pg_catalog.pg_class t ON i.indrelid   = t.oid
    JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(i.indkey)
WHERE c.relkind = 'i'
      AND n.nspname NOT IN ('pg_catalog', 'pg_toast')
      AND pg_catalog.pg_table_is_visible(c.oid)
GROUP BY
    n.nspname
    ,t.relname
    ,c.relname
    ,i.indisunique
    ,i.indexrelid
ORDER BY
    n.nspname
    ,t.relname
    ,c.relname;

我发现使用函数的索引不链接到列名,所以偶尔会找到一个索引列表,例如一个列名实际上是使用3。

例:

1
CREATE INDEX ui1 ON table1 (COALESCE(col1,''),COALESCE(col2,''),col3)

查询仅返回"col3"作为索引上的列,但DDL显示索引中使用的完整列集。


延伸到@ Cope360的好答案。要获取某个表(包括它们是相同的表名但不同的模式),只需使用表OID。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SELECT
     t.relname AS TABLE_NAME
    ,i.relname AS index_name
    ,a.attname AS column_name
    ,a.attrelid tableid

FROM
    pg_class t,
    pg_class i,
    pg_index ix,
    pg_attribute a
WHERE
    t.oid = ix.indrelid
    AND i.oid = ix.indexrelid
    AND a.attrelid = t.oid
    AND a.attnum = ANY(ix.indkey)
    AND t.relkind = 'r'
    -- and t.relname like 'tbassettype'
    AND a.attrelid = '"dbLegal".tbassettype'::regclass
ORDER BY
    t.relname,
    i.relname;

说明:我在模式'dbAsset'和'dbLegal'中都有表名'tbassettype'。要仅获取dbLegal上的表,只需让a.attrelid =其OID。


@ cope360的一点修改回答:

1
2
3
4
5
6
7
8
9
10
CREATE TABLE test (a INT, b INT, c INT, CONSTRAINT pk_test PRIMARY KEY(c, a, b));
SELECT i.relname AS index_name,
       ix.indisunique AS is_unique,
       a.attname AS column_name,
FROM pg_class c
       INNER JOIN pg_index ix ON c.oid=ix.indrelid
       INNER JOIN pg_class i ON ix.indexrelid=i.oid
       INNER JOIN pg_attribute a ON a.attrelid=c.oid AND a.attnum=any(ix.indkey)
WHERE c.oid='public.test'::regclass::oid
ORDER BY array_position(ix.indkey, a.attnum) ASC;

这将以正确的顺序显示索引列:

1
2
3
4
index_name      is_unique  column_name
pk_test         TRUE       c
pk_test         TRUE       a
pk_test         TRUE       b


1
2
3
4
5
6
7
8
9
10
11
SELECT t.relname AS TABLE_NAME,
       i.relname AS index_name,
       array_position(ix.indkey,a.attnum) pos,
       a.attname AS column_name
FROM pg_class t
JOIN pg_index ix ON t.oid = ix.indrelid
JOIN pg_class i ON i.oid = ix.indexrelid
JOIN pg_attribute a ON a.attrelid = t.oid AND a.attnum = ANY(ix.indkey)
WHERE t.relkind = 'r'
AND t.relname LIKE 'orders'
ORDER BY t.relname, i.relname, array_position(ix.indkey,a.attnum)