Postgres: SQL tablodaki yabancı anahtarları listeleyecek


Yanıtlar:


376

Bunu information_schema tabloları üzerinden yapabilirsiniz. Örneğin:

SELECT
    tc.table_schema, 
    tc.constraint_name, 
    tc.table_name, 
    kcu.column_name, 
    ccu.table_schema AS foreign_table_schema,
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name 
FROM 
    information_schema.table_constraints AS tc 
    JOIN information_schema.key_column_usage AS kcu
      ON tc.constraint_name = kcu.constraint_name
      AND tc.table_schema = kcu.table_schema
    JOIN information_schema.constraint_column_usage AS ccu
      ON ccu.constraint_name = tc.constraint_name
      AND ccu.table_schema = tc.table_schema
WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name='mytable';

8
table_name = 'mytable' tc.table_name = 'mytable' olmalıdır, yoksa belirsiz bir hata atar
intrepion

15
+1, çok yararlı. Sorguyu daha sağlam hale getirmek için, büyük olasılıkla constraint_schema'ya da katılmalıdır, çünkü iki şemanın aynı ada sahip kısıtlamaları olması mümkündür. Gibi bir şey: FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu USING (constraint_schema, constraint_name) JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name)
EMP

8
Kısıtlamada birkaç sütun olduğunda bu kesilir, değil mi? Bilgi sütunları BTW kullanarak pk sütunlarını fk sütunlarıyla ilişkilendirmenin uygun bir yolu yoktur.
fionbio

5
Gerçekten de kısıtlı olarak birden fazla sütunla kırılıyor. Postgres için bu bilgiyi pg_catalog şemasından almanın bir yolu vardır. Cevabımı aşağıda görebilirsiniz.
martin

9
Sorgu yanlış. Kısıtlama adlarının tekrarlanamayacağını varsayar; bu yanlıştır. Aynı adda kısıtlamalar farklı ad alanlarında bulunabilir. Birleştirme yapmak için kısıt_adı kullanıyorsunuz. Ayrıca, iki kısıtlamanın aynı olduğundan emin olmadığınız için hem kısıt_adı hem de şema adına katılmak işe yaramaz. Tek seçenek pg_constraints, pg_class vb. İçin katılmak için oids kullanmaktır. Postgres'in ANSI kataloğu sadece uyum için var ama kusurlu. pg_catalog gidilecek yoldur. Doğru cevap burada dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova

69

psql bunu yapar ve psql ile aşağıdakileri başlatırsanız:

psql -E

tam olarak hangi sorgunun yürütüldüğünü gösterecektir. Yabancı anahtar bulma durumunda:

SELECT conname,
  pg_catalog.pg_get_constraintdef(r.oid, true) as condef
FROM pg_catalog.pg_constraint r
WHERE r.conrelid = '16485' AND r.contype = 'f' ORDER BY 1

Bu durumda, 16485 baktığım tablonun yağıdır - bunu tablename'nizi aşağıdaki gibi regclass'a dökerek alabilirsiniz:

WHERE r.conrelid = 'mytable'::regclass

Benzersiz değilse (veya ilkinizdeki) tablo adını şema niteleyerek belirleyin search_path:

WHERE r.conrelid = 'myschema.mytable'::regclass

2
Bu çok kullanışlı! Postgres, bunun gibi her şeyi basitleştiren milyonlarca küçük işleve sahip gibi görünüyor. Şimdi onları nasıl hatırlayabilirim?
epic_fil

5
@Phil: Sadece genel bir fikre ihtiyacınız var. Kılavuzun geri kalanını hatırlamasına izin verin.
Erwin Brandstetter

3
tabloyu hedefleyen tüm yabancı anahtarları listelemek için:SELECT conname, pg_catalog.pg_get_constraintdef(r.oid, true) as condef FROM pg_catalog.pg_constraint r WHERE r.confrelid = 'myschema.mytable'::regclass;
regilero

1
@ErwinBrandstetter Yabancı bir tablo adı almak için nasıl yaparım?
Wellington Silva Ribeiro

2
Anlamıyorum, hangi komutu kullanmalıyım? psql -E -U username -d database ThenWHAT?
Poutrathor

49

Sayı \d+ tablenamePostgreSQL isteminde üzerinde, masa sütunun veri türlerini göstermenin yanı sıra bu dizinleri ve yabancı anahtarları göstereceğiz.


Üzgünüm, yorumumun kırpıldığını fark etmedim. En azından bir kez deneyebilseydiniz, yabancı anahtar eşlemelerinin de görüntülendiğini görürsünüz.
Gre Hahn

45

Ollyc'in cevabı Postgres'e özgü olmadığı için iyidir, ancak yabancı anahtar birden fazla sütuna başvurduğunda bozulur. Aşağıdaki sorgu rasgele sayıda sütun için çalışmaktadır, ancak büyük oranda Postgres uzantılarına dayanmaktadır:

select 
    att2.attname as "child_column", 
    cl.relname as "parent_table", 
    att.attname as "parent_column",
    conname
from
   (select 
        unnest(con1.conkey) as "parent", 
        unnest(con1.confkey) as "child", 
        con1.confrelid, 
        con1.conrelid,
        con1.conname
    from 
        pg_class cl
        join pg_namespace ns on cl.relnamespace = ns.oid
        join pg_constraint con1 on con1.conrelid = cl.oid
    where
        cl.relname = 'child_table'
        and ns.nspname = 'child_schema'
        and con1.contype = 'f'
   ) con
   join pg_attribute att on
       att.attrelid = con.confrelid and att.attnum = con.child
   join pg_class cl on
       cl.oid = con.confrelid
   join pg_attribute att2 on
       att2.attrelid = con.conrelid and att2.attnum = con.parent

8.4'ten önce ilk olarak, unnest işlevi yaratılmalıdır. wiki.postgresql.org/wiki/Array_Unnest
maletin

Bu sorguya tablo adı nereye eklenir? Yukarıdaki kelimeye, PSQL DB'mde onlarca yabancı anahtar bulunan 0 satır döndürülür.
Phrogz

4
'Child_table' ve 'child_schema' ifadelerini tablonun ve şemasının adlarıyla değiştirirsiniz
martin

bu size fkey ismini söylemez.
Evan Carroll

@EvanCarroll Yanıtımı anahtarın adını içerecek şekilde güncelledim.
martin

31

Ollyc tarifi uzantısı:

CREATE VIEW foreign_keys_view AS
SELECT
    tc.table_name, kcu.column_name,
    ccu.table_name AS foreign_table_name,
    ccu.column_name AS foreign_column_name
FROM
    information_schema.table_constraints AS tc
    JOIN information_schema.key_column_usage 
        AS kcu ON tc.constraint_name = kcu.constraint_name
    JOIN information_schema.constraint_column_usage 
        AS ccu ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY';

Sonra:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';


Teşekkürler, yeniden kullanım için ideal.
schellingerht

16

Çözümünüz için ff gönderisini kontrol edin ve bunu yararlı bulduğunuzda işaretlemeyi unutmayın

http://errorbank.blogspot.com/2011/03/list-all-foreign-keys-references-for.html

SELECT
  o.conname AS constraint_name,
  (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema,
  m.relname AS source_table,
  (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column,
  (SELECT nspname FROM pg_namespace WHERE oid=f.relnamespace) AS target_schema,
  f.relname AS target_table,
  (SELECT a.attname FROM pg_attribute a WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column
FROM
  pg_constraint o LEFT JOIN pg_class f ON f.oid = o.confrelid LEFT JOIN pg_class m ON m.oid = o.conrelid
WHERE
  o.contype = 'f' AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r');

PostgreSQL 9.1 üzerinde çalışan iki SQL sunar (yanlış kaçışını düzelttikten sonra 'tablename' (şema öneki olmadan) SQL'e koyun).
alfonx

2
+1: yinelenenleri döndürmeyen tek çözüm budur.
Olivier MATROT

Bu çözüm, iyi çalışıyor ve kopyaları döndürmüyor.
Fuhrmann

1
Bu çözüm, herhangi bir çok sütunlu yabancı anahtarın sadece ilk sütununu gösterecektir ... ancak az önce yapacağımdan çok daha basit görünüyor.
dewin

12

Bu sorgu bileşik anahtarlarla da doğru çalışır:

select c.constraint_name
    , x.table_schema as schema_name
    , x.table_name
    , x.column_name
    , y.table_schema as foreign_schema_name
    , y.table_name as foreign_table_name
    , y.column_name as foreign_column_name
from information_schema.referential_constraints c
join information_schema.key_column_usage x
    on x.constraint_name = c.constraint_name
join information_schema.key_column_usage y
    on y.ordinal_position = x.position_in_unique_constraint
    and y.constraint_name = c.unique_constraint_name
order by c.constraint_name, x.ordinal_position

2
"Kısıt_adı" üzerindeki sütunlara katılıyorsunuz, bu yalnızca kısıtlama adlarınızın tümü benzersizse (tüm şemalardaki tüm tablolarda) işe yarar. Bu genellikle bir gereklilik değildir ve bu nedenle veritabanı tarafından zorunlu tutulmaz.
Zilk

3
Teşekkürler. Birden fazla sütunu düzgün işlemek için information_schema'nın nasıl kullanılacağını gösteren tek cevap budur.
Samuel Danielson

Bu çözüm işe yarıyor. Yinelemeleri üretmez ve FK'de birden çok alanı işler.
Igor

9

Ben ne aradığını ve @ollyc ne yazdı çok yakın olduğunu düşünüyorum:

SELECT
tc.constraint_name, tc.table_name, kcu.column_name, 
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name 
FROM 
information_schema.table_constraints AS tc 
JOIN information_schema.key_column_usage AS kcu
  ON tc.constraint_name = kcu.constraint_name
JOIN information_schema.constraint_column_usage AS ccu
  ON ccu.constraint_name = tc.constraint_name
WHERE constraint_type = 'FOREIGN KEY' AND ccu.table_name='YourTableNameHere';

Bu, belirttiğiniz tabloyu yabancı anahtar olarak kullanan tüm tabloları listeler


9

kısa ama tatlı sizin için işe yarar.

select  * from information_schema.key_column_usage where constraint_catalog=current_catalog and table_name='your_table_name' and position_in_unique_constraint notnull;

PG 12.2
Jack Kinsella

5

Mevcut cevapların hiçbiri bana aslında onları istediğim şekilde sonuç vermedi. İşte işte yabancı anahtarlar hakkında bilgi bulmak için (muazzam) sorgum.

Birkaç not:

  • Postgres 9.4 ve sonrasında kullandığım ifadeleri oluşturmak from_colsve to_colskullanmak için kullandığım WITH ORDINALITYpencere işlevini kullanmak yerine büyük ölçüde basitleştirilebilir .
  • Aynı ifadeler, sonuçların döndürülen sırasını değiştirmeyen sorgu planlayıcısına dayanıyor UNNEST . Bunun olacağını düşünmüyorum, ancak veri kümemde test edilecek çok sütunlu yabancı anahtarım yok. 9.4 incelik eklemek bu olasılığı tamamen ortadan kaldırır.
  • Sorgunun kendisi Postgres 9.0 veya üstünü gerektirir (8.x ORDER BYtoplu işlevlerde izin vermedi )
  • Değiştir STRING_AGGile ARRAY_AGGsütun dizisi yerine virgülle ayrılmış dize istiyorum.

-

SELECT
    c.conname AS constraint_name,
    (SELECT n.nspname FROM pg_namespace AS n WHERE n.oid=c.connamespace) AS constraint_schema,

    tf.name AS from_table,
    (
        SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq)
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
                    attnum
                FROM
                    UNNEST(c.conkey) AS t(attnum)
            ) AS t
            INNER JOIN pg_attribute AS a ON a.attrelid=c.conrelid AND a.attnum=t.attnum
    ) AS from_cols,

    tt.name AS to_table,
    (
        SELECT STRING_AGG(QUOTE_IDENT(a.attname), ', ' ORDER BY t.seq)
        FROM
            (
                SELECT
                    ROW_NUMBER() OVER (ROWS UNBOUNDED PRECEDING) AS seq,
                    attnum
                FROM
                    UNNEST(c.confkey) AS t(attnum)
            ) AS t
            INNER JOIN pg_attribute AS a ON a.attrelid=c.confrelid AND a.attnum=t.attnum
    ) AS to_cols,

    CASE confupdtype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_update,
    CASE confdeltype WHEN 'r' THEN 'restrict' WHEN 'c' THEN 'cascade' WHEN 'n' THEN 'set null' WHEN 'd' THEN 'set default' WHEN 'a' THEN 'no action' ELSE NULL END AS on_delete,
    CASE confmatchtype::text WHEN 'f' THEN 'full' WHEN 'p' THEN 'partial' WHEN 'u' THEN 'simple' WHEN 's' THEN 'simple' ELSE NULL END AS match_type,  -- In earlier postgres docs, simple was 'u'nspecified, but current versions use 's'imple.  text cast is required.

    pg_catalog.pg_get_constraintdef(c.oid, true) as condef
FROM
    pg_catalog.pg_constraint AS c
    INNER JOIN (
        SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name
        FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
    ) AS tf ON tf.oid=c.conrelid
    INNER JOIN (
        SELECT pg_class.oid, QUOTE_IDENT(pg_namespace.nspname) || '.' || QUOTE_IDENT(pg_class.relname) AS name
        FROM pg_class INNER JOIN pg_namespace ON pg_class.relnamespace=pg_namespace.oid
    ) AS tt ON tt.oid=c.confrelid
WHERE c.contype = 'f' ORDER BY 1;

5

Başka bir yol:

WITH foreign_keys AS (
    SELECT
      conname,
      conrelid,
      confrelid,
      unnest(conkey)  AS conkey,
      unnest(confkey) AS confkey
    FROM pg_constraint
    WHERE contype = 'f' -- AND confrelid::regclass = 'your_table'::regclass
)
-- if confrelid, conname pair shows up more than once then it is multicolumn foreign key
SELECT fk.conname as constraint_name,
       fk.confrelid::regclass as referenced_table, af.attname as pkcol,
       fk.conrelid::regclass as referencing_table, a.attname as fkcol
FROM foreign_keys fk
JOIN pg_attribute af ON af.attnum = fk.confkey AND af.attrelid = fk.confrelid
JOIN pg_attribute a ON a.attnum = conkey AND a.attrelid = fk.conrelid
ORDER BY fk.confrelid, fk.conname
;


4

Anahtarların başvurduğu Birincil Anahtarın adını kullanın ve information_schema'yı sorgulayın:

select table_name, column_name
from information_schema.key_column_usage
where constraint_name IN (select constraint_name
  from information_schema.referential_constraints 
  where unique_constraint_name = 'TABLE_NAME_pkey')

Burada 'TABLE_NAME_pkey' Yabancı Anahtarlar tarafından belirtilen Birincil Anahtarın adıdır.


4

İşte PostgreSQL posta listesinden Andreas Joseph Krogh'un bir çözümü: http://www.postgresql.org/message-id/200811072134.44750.andreak@officenet.no

SELECT source_table::regclass, source_attr.attname AS source_column,
    target_table::regclass, target_attr.attname AS target_column
FROM pg_attribute target_attr, pg_attribute source_attr,
  (SELECT source_table, target_table, source_constraints[i] source_constraints, target_constraints[i] AS target_constraints
   FROM
     (SELECT conrelid as source_table, confrelid AS target_table, conkey AS source_constraints, confkey AS target_constraints,
       generate_series(1, array_upper(conkey, 1)) AS i
      FROM pg_constraint
      WHERE contype = 'f'
     ) query1
  ) query2
WHERE target_attr.attnum = target_constraints AND target_attr.attrelid = target_table AND
      source_attr.attnum = source_constraints AND source_attr.attrelid = source_table;

Bu çözüm, birden çok sütuna başvuran yabancı anahtarları işler ve yinelemeleri önler (diğer yanıtların bazıları başarısız olur). Değiştirdiğim tek şey değişken isimlerdi.

Tabloya employeebaşvuran tüm sütunları döndüren bir örnek permission:

SELECT source_column
FROM foreign_keys
WHERE source_table = 'employee'::regclass AND target_table = 'permission'::regclass;

4

Martin'in mükemmel cevabını genişletmek için, üst tabloya göre filtrelemenizi sağlayan ve her bir üst tablo ile alt tablonun adını gösteren bir sorgu, böylece yabancı anahtar kısıtlamalarına dayalı tüm bağımlı tabloları / sütunları görebilirsiniz. üst tablo.

select 
    con.constraint_name,
    att2.attname as "child_column", 
    cl.relname as "parent_table", 
    att.attname as "parent_column",
    con.child_table,
    con.child_schema
from
   (select 
        unnest(con1.conkey) as "parent", 
        unnest(con1.confkey) as "child", 
        con1.conname as constraint_name,
        con1.confrelid, 
        con1.conrelid,
        cl.relname as child_table,
        ns.nspname as child_schema
    from 
        pg_class cl
        join pg_namespace ns on cl.relnamespace = ns.oid
        join pg_constraint con1 on con1.conrelid = cl.oid
    where  con1.contype = 'f'
   ) con
   join pg_attribute att on
       att.attrelid = con.confrelid and att.attnum = con.child
   join pg_class cl on
       cl.oid = con.confrelid
   join pg_attribute att2 on
       att2.attrelid = con.conrelid and att2.attnum = con.parent
   where cl.relname like '%parent_table%'       

1
Kabul edilen cevaptaki sorgu ~ 0.03 sorgusuna 1.2 saniye ekler, sizinkine sadece 0.01 eklenir, teşekkürler!
AVProgrammer

3

Kullanarak information_schema, çoklu sütun anahtarlarıyla çalışarak, her iki tabloda farklı adların sütunlarını doğru bir şekilde birleştirerek ve aynı zamanda ms sqlsever ile uyumlu olan soruna uygun çözüm:

select fks.TABLE_NAME as foreign_key_table_name
, fks.CONSTRAINT_NAME as foreign_key_constraint_name
, kcu_foreign.COLUMN_NAME as foreign_key_column_name
, rc.UNIQUE_CONSTRAINT_NAME as primary_key_constraint_name
, pks.TABLE_NAME as primary_key_table_name
, kcu_primary.COLUMN_NAME as primary_key_column_name
from INFORMATION_SCHEMA.TABLE_CONSTRAINTS fks -- foreign keys
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu_foreign -- the columns of the above keys
    on fks.TABLE_CATALOG = kcu_foreign.TABLE_CATALOG
    and fks.TABLE_SCHEMA = kcu_foreign.TABLE_SCHEMA
    and fks.TABLE_NAME = kcu_foreign.TABLE_NAME
    and fks.CONSTRAINT_NAME = kcu_foreign.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc -- referenced constraints
    on rc.CONSTRAINT_CATALOG = fks.CONSTRAINT_CATALOG
    and rc.CONSTRAINT_SCHEMA = fks.CONSTRAINT_SCHEMA
    and rc.CONSTRAINT_NAME = fks.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.TABLE_CONSTRAINTS pks -- primary keys (referenced by fks)
    on rc.UNIQUE_CONSTRAINT_CATALOG = pks.CONSTRAINT_CATALOG
    and rc.UNIQUE_CONSTRAINT_SCHEMA = pks.CONSTRAINT_SCHEMA
    and rc.UNIQUE_CONSTRAINT_NAME = pks.CONSTRAINT_NAME
inner join INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu_primary
    on pks.TABLE_CATALOG = kcu_primary.TABLE_CATALOG
    and pks.TABLE_SCHEMA = kcu_primary.TABLE_SCHEMA
    and pks.TABLE_NAME = kcu_primary.TABLE_NAME
    and pks.CONSTRAINT_NAME = kcu_primary.CONSTRAINT_NAME
    and kcu_foreign.ORDINAL_POSITION = kcu_primary.ORDINAL_POSITION -- this joins the columns
where fks.TABLE_SCHEMA = 'dbo' -- replace with schema name
and fks.TABLE_NAME = 'your_table_name' -- replace with table name
and fks.CONSTRAINT_TYPE = 'FOREIGN KEY'
and pks.CONSTRAINT_TYPE = 'PRIMARY KEY'
order by fks.constraint_name, kcu_foreign.ORDINAL_POSITION

Not: Potgresql ve sqlserver uygulamaları arasında information_schema, en üst yanıtı iki sistemde farklı sonuçlar veren bazı farklılıklar vardır - biri yabancı anahtar tablosu için sütun isimlerini diğeri birincil anahtar tablosu için gösterir. Bu nedenle bunun yerine KEY_COLUMN_USAGE görünümünü kullanmaya karar verdim.


Bilgi şeması doğru cevap gibi görünüyor, ama gerçekten pg_catalog tabloları istiyorum: pg_constraint vb. Biz bu şekilde ısırıldı. veritabanınızda büyük miktarda kısıtlama varsa performans sorunları olabilir ...
hajikelist

Yukarıdaki koşul, ORDINAL_POSITIONyabancı anahtardaki sütunların sırası, benzersiz kısıtlamadaki sütunların sırasından farklı olduğunda yanlış sonuç verebilir. Ben size katılmalıydın inanıyoruz kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Güncelleme seni kaldırmak gerektiğini düşünüyorum böylece Ayrıca, bir yabancı anahtar, hem de UNIQUE sınırlamasıyla bağlı olabilir: pks.CONSTRAINT_TYPEkoşul ve sadece katılabilir rciçin kcu_primarydoğrudan
EASD

Burada benzer bir cevap
verdim

2
SELECT r.conname
      ,ct.table_name
      ,pg_catalog.pg_get_constraintdef(r.oid, true) as condef
  FROM pg_catalog.pg_constraint r, information_schema.constraint_table_usage ct
 WHERE r.contype = 'f' 
   AND r.conname = ct.constraint_name
 ORDER BY 1

2

Sıklıkla beğenen ve kullanan bir çözüm yazdım. Kod http://code.google.com/p/pgutils/ adresindedir. . Pgutils.foreign_keys görünümüne bakın.

Ne yazık ki, çıktı buraya eklenemeyecek kadar garip. Ancak, burada veritabanının genel bir sürümünde deneyebilirsiniz, şöyle:

$ psql -h unison-db.org -U PUBLIC -d unison -c 'select * from pgutils.foreign_keys;

Bu en azından 8.3 ile çalışır. Önümüzdeki birkaç ay içinde gerekirse güncellenmesini bekliyorum.

-Reece


1
Proje bağlantısı artık öldü.
pimlottc

@pimlottc: taşındı bitbucket.org/reece/pgutils . Bunu işaret ettiğiniz için teşekkürler.
Reece


0

Not: Kısıtlama sütunlarını okurken sütunun sırasını unutmayın!

SELECT conname, attname
  FROM pg_catalog.pg_constraint c 
  JOIN pg_catalog.pg_attribute a ON a.attrelid = c.conrelid AND a.attnum = ANY (c.conkey)
 WHERE attrelid = 'schema.table_name'::regclass
 ORDER BY conname, array_position(c.conkey, a.attnum)

0

Şu anda kullandığım şey bu, bir tablo listeleyecek ve fkey kısıtlamaları [tablo yan tümcesini kaldır ve geçerli katalogdaki tüm tabloları listeleyecektir]:

SELECT

    current_schema() AS "schema",
    current_catalog AS "database",
    "pg_constraint".conrelid::regclass::text AS "primary_table_name",
    "pg_constraint".confrelid::regclass::text AS "foreign_table_name",

    (
        string_to_array(
            (
                string_to_array(
                    pg_get_constraintdef("pg_constraint".oid),
                    '('
                )
            )[2],
            ')'
        )
    )[1] AS "foreign_column_name",

    "pg_constraint".conindid::regclass::text AS "constraint_name",

    TRIM((
        string_to_array(
            pg_get_constraintdef("pg_constraint".oid),
            '('
        )
    )[1]) AS "constraint_type",

    pg_get_constraintdef("pg_constraint".oid) AS "constraint_definition"

FROM pg_constraint AS "pg_constraint"

JOIN pg_namespace AS "pg_namespace" ON "pg_namespace".oid = "pg_constraint".connamespace

WHERE
    --fkey and pkey constraints
    "pg_constraint".contype IN ( 'f', 'p' )
    AND
    "pg_namespace".nspname = current_schema()
    AND
    "pg_constraint".conrelid::regclass::text IN ('whatever_table_name')

0

tamamen bu cevaba dayanarak bash cevabında doğrudan doğrulamak için en hızlı

IFS='' read -r -d '' sql_code << EOF_SQL_CODE
      SELECT
      o.oid
      , o.conname AS constraint_name
      , (SELECT nspname FROM pg_namespace WHERE oid=m.relnamespace) AS source_schema
      , m.relname AS source_table
      , (SELECT a.attname FROM pg_attribute a
      WHERE a.attrelid = m.oid AND a.attnum = o.conkey[1] AND a.attisdropped = false) AS source_column
      , (SELECT nspname FROM pg_namespace
      WHERE oid=f.relnamespace) AS target_schema
      , f.relname AS target_table
      , (SELECT a.attname FROM pg_attribute a
      WHERE a.attrelid = f.oid AND a.attnum = o.confkey[1] AND a.attisdropped = false) AS target_column
      , ROW_NUMBER () OVER (ORDER BY o.oid) as rowid
      FROM pg_constraint o
      LEFT JOIN pg_class f ON f.oid = o.confrelid
      LEFT JOIN pg_class m ON m.oid = o.conrelid
      WHERE 1=1
      AND o.contype = 'f'
      AND o.conrelid IN (SELECT oid FROM pg_class c WHERE c.relkind = 'r')
EOF_SQL_CODE

psql -d my_db -c "$sql_code"
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.