PostgreSQL'de dizinli sütunları listele


233

PostgreSQL bir dizin üzerinde olan sütunları almak istiyorum.

MySQL'de sütunu kullanabilir SHOW INDEXES FOR tableve Column_namesütuna bakabilirsiniz .

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 için böyle bir şey var mı?

Denedim \dde psql(ile istemi komuta -ESQL gösterme seçeneğinin) ama aradığım bilgiyi göstermez.

Güncelleme: Cevaplarını ekleyen herkese teşekkürler. cope360 bana tam olarak aradığım şeyi verdi, ancak birkaç kişi çok faydalı bağlantılar verdi. İleride başvurmak için pg_index ( Milen A. Radev aracılığıyla) belgelerine ve PostgreSQL'den META bilgilerinin çıkarılması ( Michał Niklas aracılığıyla ) adlı çok faydalı makaleye göz atın .


Sadece açıklığa kavuşturmak için: Programınızın çalışma zamanında hangi sütunların dizine eklendiğini anlayabilmesini istiyorsunuz, değil mi? Aksine programlama bilmek.
Wayne Conrad

Evet doğru. İdeal olarak ben sadece dizin üzerinde olan sütunları listeleyen bir SQL deyimi istiyorum. Ama PostgreSQL'in
MySQL'den

Yanıtlar:


261

Bazı test verileri oluşturun ...

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

Dizinleri ve dizine eklenen sütunları listele:

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

Sütun adlarını toplayın:

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

24
Doldurulmuş bir veritabanında dizinleri bulmaya çalışan herkes için: bu sorgu harika çalışıyor, ancak and t.relname like 'test%'satırı istediğiniz tablo (lar) a değiştirin veya db'nizdeki tüm dizinleri bulmak için bu satırı tamamen silin.
Erik J

1
Birisi ne relkind='r'anlama geldiğini açıklayabilir mi?
Qwerty

5
@Qwery, pg_class belgelerine bakın r = ordinary table, i = index, S = sequence, v = view, c = composite type, t = TOAST table.
cope360

1
anahtarın benzersizliğini anlatmanın bir yolu var mı?
Andrew

2
endeks benzersizliğini görmek için de seçinix.indisunique
Jana

177

PostgreSQL ( pg_indexes ):

SELECT * FROM pg_indexes WHERE tablename = 'mytable';

MySQL ( GÖSTER ENDEKSİ ):

SHOW INDEX FROM mytable;

3
Bu, en basit cevaptır ve "Sütunum dizine eklenmiş mi?" Sorusunu yanıtlamak açısından en ilginç cevaptır. PostgreSQL: SELECT COUNT(indexname) AS indexcount FROM pg_indexes WHERE tablename='mytablename' AND indexdef LIKE '%mycolumnname%' ;ve doğrulayın indexcount>0. mySQL: SHOW INDEX FROM mytablename WHERE Column_name='mycolumnname' ;ve sonuç kümesinin boş olmadığını doğrulayın.
zerobandwidth

2
Bu, dizinler hakkında hızlı bilgi almak açısından çok yararlı bir cevap olsa da, pg_indexesgörünüm sütun adları sağlamadığı için orijinal soruyu cevaplamaz . postgresql.org/docs/current/view-pg-indexes.html
akagixxer

146

\d table_namebu bilgileri gösterir psql, ancak SQL kullanarak veritabanından bu tür bilgileri almak istiyorsanız PostgreSQL'den META bilgilerini ayıklama konusuna bakın .

Test ve üretim ortamlarında PostgreSQL veritabanlarını karşılaştırmak için db şemasından bazı bilgileri rapor etmek için yardımcı programımda bu bilgileri kullanıyorum .


Postgres'ten meta bilgi çıkarma bağlantınız tam olarak aradığım şey! Bu konudaki ipuçlarını ve bazı kazma yöntemlerini kullanarak bu yazıda kullandığı sorguya oldukça yaklaştım, ancak hepsi bu şekilde ortaya koymak güzel.
Luke Francl

1
AWS RDS PostgreSQL 9.6.5 kullanıyorum ve \d tableherhangi bir dizin göstermiyor, ancak \ditüm dizinleri gösteriyor.
Hendy Irawan

@HendyIrawan görünüşe göre diğer ayarlardan etkilenebilir. Merak gibi "sadece tuples" modu (geçiş tarafından \t) vardı. "Sadece tuples" açıkken, ben \d"sadece tuples" kapalı, ben indeks alamadım . Bu psql (PostgreSQL) 9.6.15 ile.
JMM

77

Sadece yap: \d table_name

Ancak, sütunlarla ilgili bilgilerin orada olmadığından ne demek istediğinden emin değilim.

Örneğin:

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

Dizin verilen sütunların bu tabloda olduğunu açıkça gösterir.


Bir tablodaki tüm dizinleri yapmama izin verecek bir şey umuyordum ama haklısın, \d index_namebilgiye sahip. Böylece bir tablodaki indekslere bakabilirim, daha sonra detaylara bakabilirim. Sütunları göstermeyerek, \d tableisimle oluşturulan SQL'e baktığımı ve sütun listesinin nereden geldiğini açıkça görmüyorum demek istiyorum . Sanırım yapmamayı tercih ettiğim indeks tanımından ayrıştırılıyor.
Luke Francl

AWS RDS PostgreSQL 9.6.5 kullanıyorum ve \d tableherhangi bir dizin göstermiyor, ancak \ditüm dizinleri gösteriyor.
Hendy Irawan

37

# \di

Kolaylıklar ve en kısa yol, \digeçerli veritabanındaki tüm dizinleri listeleyecektir.

$ \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\dgeçerli d atabase'in tüm ilişkilerini listeleyecek komutun "küçük kardeşi" dir. Bu yüzden \dikesinlikle "bana bu d atabases i ndexes göster" anlamına gelir.

Yazma \diS, sistem genelinde kullanılan tüm dizinleri listeleyecektir, yani tüm pg_catalog dizinlerini de alırsınız.

$ \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-- 

Bu komutların her ikisiyle de +, dizinin ihtiyaç duyduğu disk alanının boyutu ve varsa bir açıklama gibi daha fazla bilgi almak için ardına ekleyebilirsiniz .

$ \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'de komut yazma konusunda yardım bulabilirsiniz \?.


2
Ancak, dizinlerin oluşturulduğu sütun adlarını göstermez. Bileşik birincil anahtarlar dizininde çok sayıda sütun var ve bunlar görülemiyor.
Vignesh Raja

18

Diğer kodlarla birlikte ve bir görünüm oluşturdu:

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;

12

Bazı örnek veriler ...

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_indexdefFonksiyonu kullanın :

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)

Basit ve etkili!
David

Sadece müthiş. Bu cevapta ilerlediğim için şanslıyım.
greatvovan

8

Bu komutlar, tablo değişkenlerinin, dizinlerin ve kısıtlamaların görünümünü de gösterir

=# \d table_name;

Misal:

testannie=# \d dv.l_customer_account;

7

\d tablename 8.3.8 sürümünde benim için sütun adlarını gösterir.

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

7

QUERY SONUCU:

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)

SORGU:

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;

güzel, ancak bir sütun için "sütun" adı ayrılmış bir kelimedir. Şema için IDEM, column_name kullanmalıdır
parisni

5

Ham bilgi pg_index içinde .


İlginç. Özellikle indkey: "Bu, bu indeksin hangi tablo sütunlarını endekslediğini gösteren indnatts değerleri dizisidir. Örneğin 1 3 değeri, birinci ve üçüncü tablo sütunlarının dizin anahtarını oluşturduğu anlamına gelir. Bu dizideki sıfır, karşılık gelen dizin özniteliği, basit bir sütun başvurusu yerine tablo sütunları üzerinde bir ifadedir "
Luke Francl

2

Dizindeki sütun sırasını korumak istiyorsanız, bunu yapmanın (çok çirkin) bir yolu var:

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

sütun sırası pg_index.indkey sütununda saklanır, bu yüzden o diziden aboneler tarafından sipariş.


2

Dizinlerle oynatılırken, dizinde hangi sütunların oluşturulma sırası sütunların kendisi kadar önemlidir.

Aşağıdaki sorgu, belirli bir tablo için tüm dizinleri ve tüm sütunlarını sıralı bir şekilde listeler.

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

2
OP neden bunu denemeli? Bir güzel cevap hep ne yapıldı bir açıklama elde eder ve bunun da OP için ama bu soruyu bulabilir ve cevabınızı okuma SO gelecek ziyaretçiler için değil, bu şekilde yapıldığını neden.
Maximilian Ast

iordinal için çok kaygan. Sütunların doğru sırada belirtilmesini sağlar.
kbrock

Benim için işe yarayan tek cevap buydu. Sütun sırası önemlidir. (Bana inanmıyorsanız, telefon rehberinde Frank adında olan tüm insanları arayın.)
Juraj

1

Gerekli endeksleri incelemek için lütfen aşağıdaki sorguyu deneyin

Aşağıdaki gibi sorgu - ben bu şahsen denedim ve sık kullanın.

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

Kabul edilen cevaba benzer ama ettikten sol katılmak üzerine pg_attribute normal sorgu ile katılmak ya da pg_attribute doesnt vermek endeksleri gibi olan:
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;

iyi bir not, ama bu "alt (column_name") "hakkında bilgi almak için nasıl
pleerock

1

İşte cope360'ın cevabını saran bir fonksiyon :

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;

Kullanımı:

select * from getIndices('<my_table>')

Dizinlerimin işlevleri kullanan bölümlerini listelemedim (örn. "Üst (alan_adı)").
JohnMudd

0

Basit bir çözüme ne dersiniz:

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

'


Bu çözümü seviyorum. Ne yazık ki nerede yan tümceleri olan dizinlerle başarısız. (veya başka bir parantez)
kbrock

Başlangıçta parenleri atlamamayı ve ortada parens yakalamamayı ve bundan sonra her şeyi düşürmemeyi değiştirdim. '^[^\)]*\(([^\)]*)\).*$'
kbrock

0

@ cope360 'ın mükemmel yanıtı, birleştirme sözdizimini kullanmaya dönüştürüldü.

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
;

0

Bu sürüm henüz bu iş parçacığında var olduğunu düşünmüyorum: dizin için ddl ile birlikte sütun adlarının listesini sağlar.

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;

İşlevleri kullanan dizinlerin sütun adlarına bağlanmadığını buldum, bu nedenle bazen bir dizin listesi buluyorsunuz.

Misal:

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

Sorgu, dizinde yalnızca sütun olarak 'col3' değerini döndürür, ancak DDL dizinde kullanılan sütunların tamamını gösterir.


0

@ Cope360'ın iyi yanıtını genişletin. Sadece tablo OID kullanarak belirli tablo için almak (aynı tablo adı ancak farklı şema olduğu).

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;

Açıklayın: 'dbAsset' ve 'dbLegal' şemalarında 'tbassettype' tablo adım var. DbLegal'de sadece tablo almak için a.attrelid = OID değerini vermeniz yeterlidir.


0

@ Cope360'ın biraz değiştirilmiş cevabı:

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;

Bu, dizin sütunlarını doğru sırayla gösterir:

index_name      is_unique  column_name
pk_test         true       c
pk_test         true       a
pk_test         true       b

"Left join pg_attribute" kullanıldığında, hesaplanan sütunlarda, elbette NULL sütun_adı ile dizinler de gösterilir.
Paolo Bonzini

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

0

@ Cope360 tarafından kabul edilen cevap iyidir, ancak Oracle'ın DBA_IND_COLUMNS, ALL_IND_COLUMNS ve USER_IND_COLUMNS gibi biraz daha fazla bir şey istedim (örneğin, tablo / dizin şemasını ve çok sütunlu bir dizinde dizinin konumunu bildirir) buna cevap ver:

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
;

Bu şöyle bir çıktı verir:

 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.