在PostgreSQL中列出具有索引的列

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

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

 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中是否存在这样的事情?

我试过\dpsql命令提示符下(用-E选项来显示SQL),但是它没有显示我正在查找的信息。

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

创build一些testing数据…

 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)); 

列出索引和列索引:

 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 

卷起列名称:

 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_namepsql显示了这个信息,但是如果你想从使用SQL的数据库中获得这样的信息,那么看看从PostgreSQL中提取META信息 。

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

只要: \d table_name

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

例如:

 # \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) 

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

MySQL( SHOW INDEX ):

 SHOW INDEX FROM mytable; 

PostgreSQL( pg_indexes ):

 SELECT * FROM pg_indexes WHERE tablename = 'mytable'; 

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

 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; 

一些示例数据…

 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函数:

 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) 

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

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

这个命令也显示了表variables,索引和约束的视图

 =# \d table_name; 

例:

 testannie=# \d dv.l_customer_account; 

查询的结果:

 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) 

查询:

 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中 。

如果你想保持索引中的列顺序,这是一个(非常丑陋)的方式来做到这一点:

 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列中,所以我按该数组的下标sorting。

这是一个包装cope360答案的函数

 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; 

用法:

 select * from getIndices('<my_table>') 

如何简单的解决scheme:

 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%' 

`

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

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

 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 

请尝试下面的查询来深入到所需的索引

查询如下 – 我已经亲自尝试过,并经常使用它。

 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; 

类似于接受的答案,但已经作为普通连接离开 pg_attribute连接或使用pg_attribute查询没有给予像这样的索引:
create unique index unique_user_name_index on users (lower(name))

 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的优秀答案,转换为使用连接语法。

 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。

 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。

例:

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

查询只返回“col3”作为索引列,但DDL显示索引中使用的全部列。