Postgres: SQL untuk mencantumkan tabel kunci asing

219

Apakah ada cara menggunakan SQL untuk mendaftar semua kunci asing untuk tabel yang diberikan? Saya tahu nama tabel / skema dan saya bisa pasang itu.

smack0007
sumber
Saya sarankan untuk menggunakan jawaban @Magnus . Sederhana, terbersih, tercepat.
Erwin Brandstetter

Jawaban:

373

Anda dapat melakukan ini melalui tabel information_schema. Sebagai contoh:

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';
ollyc
sumber
8
table_name = 'mytable' harus berupa tc.table_name = 'mytable' atau yang lainnya akan menimbulkan kesalahan yang ambigu
intrepion
15
+1, sangat membantu. Untuk membuat kueri lebih kuat, ia mungkin juga harus bergabung dengan constraint_schema, karena dua skema mungkin memiliki kendala dengan nama yang sama. Sesuatu seperti: 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
Ini pecah ketika ada beberapa kolom dalam batasan, bukan? Tampaknya tidak ada cara yang tepat untuk mengaitkan kolom pk dengan kolom fk menggunakan information_schema BTW.
fionbio
5
Memang rusak dengan lebih dari satu kolom dalam batasan. Untuk Postgres, ada cara untuk mendapatkan informasi ini dari skema pg_catalog. Lihat jawaban saya di bawah ini.
martin
9
Kueri salah. Diasumsikan bahwa nama kendala tidak dapat diulang, yang salah. Batasan dengan nama yang sama dapat ada di ruang nama yang berbeda. Anda menggunakan constraint_name untuk membuat join. Juga bergabung di constraint_name dan nama skema tidak akan berhasil karena Anda tidak yakin kedua kendala itu sama. Satu-satunya pilihan adalah untuk pg_constraints, pg_class dll. Menggunakan oids untuk bergabung. Katalog ANSI Postgres hanya ada untuk kepatuhan tetapi cacat. pg_catalog adalah caranya. Jawaban yang benar ada di sini dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova
69

psql melakukan ini, dan jika Anda memulai psql dengan:

psql -E

itu akan menunjukkan kepada Anda apa yang dieksekusi. Dalam hal menemukan kunci asing, itu adalah:

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

Dalam hal ini, 16485 adalah angka tertinggi dari tabel yang saya lihat - Anda bisa mendapatkannya dengan hanya membuang nama tab Anda ke regclass seperti:

WHERE r.conrelid = 'mytable'::regclass

Skema-kualifikasi nama tabel jika tidak unik (atau yang pertama di Anda search_path):

WHERE r.conrelid = 'myschema.mytable'::regclass
Magnus Hagander
sumber
2
Ini sangat berguna! Postgres tampaknya memiliki sejuta fungsi kecil seperti ini yang membuat semuanya lebih sederhana. Sekarang bagaimana cara mengingatnya?
epic_fil
5
@ Phil: Anda hanya perlu ide umum. Biarkan manual mengingat sisanya.
Erwin Brandstetter
3
untuk daftar semua kunci asing yang menargetkan tabel: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, bagaimana cara saya mendapatkan nama tabel asing?
Wellington Silva Ribeiro
2
Saya tidak mengerti, perintah apa yang harus digunakan? psql -E -U username -d database ThenWHAT?
Poutrathor
49

Masalah \d+ tablenamepada prompt PostgreSQL, di samping menampilkan tipe data kolom tabel itu akan menampilkan indeks dan kunci asing.

Gre Hahn
sumber
Maaf tidak memperhatikan komentar saya terpotong. Jika Anda setidaknya bisa mencobanya sekali, Anda akan melihat pemetaan kunci asing juga ditampilkan.
Gre Hahn
45

Jawaban Ollyc baik karena tidak spesifik untuk Postgres, namun rusak ketika kunci asing merujuk lebih dari satu kolom. Query berikut berfungsi untuk jumlah kolom yang berubah-ubah tetapi sangat bergantung pada ekstensi Postgres:

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
martin
sumber
sebelum 8.4 fungsi unest harus dibuat terlebih dahulu. wiki.postgresql.org/wiki/Array_Unnest
maletin
Di mana orang memasukkan nama tabel ke dalam kueri ini? Dimasukkan secara verbatim di atas mengembalikan 0 baris pada DB PSQL saya yang memiliki puluhan kunci asing.
Phrogz
4
Anda mengganti 'child_table' dan 'child_schema' dengan nama-nama tabel dan skema
martin
ini tidak memberi tahu Anda nama si monyet.
Evan Carroll
@ EvanCarroll Saya telah memperbarui jawaban saya untuk memasukkan nama kunci.
martin
31

Perpanjangan resep ollyc:

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

Kemudian:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';

Mvoicem
sumber
Terima kasih, ideal untuk digunakan kembali.
schellingerht
16

periksa posting ff untuk solusi Anda dan jangan lupa untuk menandai ini ketika Anda merasa ini berguna

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');
Sheldon
sumber
Menawarkan dua SQL yang berfungsi pada PostgreSQL 9.1 (setelah Anda mengoreksi kesalahan, letakkan 'tablename' Anda (tanpa awalan skema) ke dalam SQL).
alfonx
2
+1: ini adalah satu-satunya solusi yang tidak mengembalikan duplikat.
Olivier MATROT
untuk solusi ini, berfungsi dengan baik dan tidak mengembalikan duplikat.
Fuhrmann
1
Solusi ini hanya akan menampilkan kolom pertama dari kunci asing multi-kolom ... tetapi terlihat jauh lebih sederhana daripada yang baru saya posting yang akan melakukan banyak.
dewin
12

Kueri ini berfungsi dengan benar dengan kunci komposit:

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
oscavi
sumber
2
Anda bergabung dengan kolom pada "constraint_name", jadi ini hanya akan berfungsi jika semua nama kendala Anda unik (di semua tabel di semua skema). Ini biasanya bukan persyaratan, dan karenanya tidak diberlakukan oleh database.
Zilk
3
Terima kasih. Ini adalah satu-satunya jawaban yang menunjukkan cara menggunakan information_schema untuk menangani beberapa kolom dengan benar.
Samuel Danielson
Solusi ini berfungsi. Itu tidak menghasilkan duplikat dan menangani beberapa bidang di FK.
Igor
9

Saya pikir apa yang Anda cari dan sangat dekat dengan apa yang ditulis @ollyc adalah ini:

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

Ini akan mencantumkan semua tabel yang menggunakan tabel yang Anda tentukan sebagai kunci asing

Shaun McCready
sumber
9

singkat tapi manis jika itu bekerja untuk Anda.

select  * from information_schema.key_column_usage where constraint_catalog=current_catalog and table_name='your_table_name' and position_in_unique_constraint notnull;
NikhilP
sumber
Membuat pesona ketika saya menulis dengan PG 12.2
Jack Kinsella
5

Tidak ada jawaban yang ada yang memberikan saya hasil dalam bentuk yang saya inginkan. Jadi, inilah pertanyaan saya (raksasa) untuk mencari informasi tentang kunci asing.

Beberapa catatan:

  • Ekspresi yang digunakan untuk menghasilkan from_colsdan to_colsbisa sangat disederhanakan pada Postgres 9.4 dan kemudian menggunakan WITH ORDINALITYdaripada peretasan fungsi-fungsi-jendela yang saya gunakan.
  • Ekspresi yang sama bergantung pada perencana kueri tidak mengubah urutan hasil yang dihasilkan dari UNNEST. Saya rasa tidak akan, tetapi saya tidak memiliki kunci asing multi-kolom dalam dataset saya untuk diuji. Menambahkan 9,4 niceties menghilangkan kemungkinan ini sama sekali.
  • Permintaan itu sendiri membutuhkan Postgres 9.0 atau lebih baru (8.x tidak mengizinkan ORDER BYfungsi agregat)
  • Ganti STRING_AGGdengan ARRAY_AGGjika Anda menginginkan array kolom daripada string yang dipisahkan koma.

-

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;
dewin
sumber
5

Satu cara lagi:

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
;
Konrad Perzyna
sumber
4

Gunakan nama Kunci Utama yang menjadi acuan Kunci dan tanyakan informasi_schema:

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

Di sini 'TABLE_NAME_pkey' adalah nama Kunci Utama yang dirujuk oleh Kunci Asing.

markmnl
sumber
4

Berikut ini adalah solusi oleh Andreas Joseph Krogh dari milis PostgreSQL: http://www.postgresql.org/message-id/[email protected]

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;

Solusi ini menangani kunci asing yang merujuk beberapa kolom, dan menghindari duplikat (yang beberapa jawaban lainnya gagal lakukan). Satu-satunya hal yang saya ubah adalah nama variabel.

Berikut adalah contoh yang mengembalikan semua employeekolom yang mereferensikan permissiontabel:

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

Untuk memperluas jawaban Martin yang unggul di sini adalah kueri yang memungkinkan Anda memfilter berdasarkan tabel induk dan menunjukkan kepada Anda nama tabel anak dengan setiap tabel induk sehingga Anda dapat melihat semua tabel / kolom dependen berdasarkan pada batasan kunci asing di tabel induk.

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%'       
Cervo
sumber
1
Kueri dalam jawaban yang diterima menambahkan 1,2 detik ke kueri ~ 0,03, Anda hanya menambahkan 0,01, terima kasih!
AVProgrammer
3

Solusi yang tepat untuk masalah ini, menggunakan information_schema, bekerja dengan tombol multi kolom, menggabungkan kolom dengan nama yang berbeda di kedua tabel dengan benar dan juga kompatibel dengan ms sqlsever:

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

Catatan: Ada beberapa perbedaan antara implementasi potgresql dan sqlserver information_schemayang membuat jawaban teratas memberikan hasil yang berbeda pada kedua sistem - satu memperlihatkan nama kolom untuk tabel kunci asing dan lainnya untuk tabel kunci primer. Karenanya, saya memutuskan untuk menggunakan tampilan KEY_COLUMN_USAGE.

jakubiszon
sumber
Skema informasi sepertinya jawaban yang tepat, tetapi Anda benar-benar menginginkan tabel pg_catalog: pg_constraint dll. jika database Anda memiliki sejumlah besar kendala akan ada masalah kinerja ...
hajikelist
Kondisi di atas ORDINAL_POSITIONdapat menghasilkan hasil yang salah ketika urutan kolom dalam kunci asing berbeda dari urutan kolom dalam batasan unik. Saya percaya Anda harus bergabung di kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Pembaruan : Juga, kunci asing mungkin bergantung pada batasan UNIK juga, jadi saya pikir Anda harus menghapus pks.CONSTRAINT_TYPEkondisi dan hanya dapat bergabung rcuntuk kcu_primarylangsung
easd
Saya telah membuat jawaban yang serupa di sini: stackoverflow.com/a/62260908/9093051
easd
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
Pugazendhi Asaimuthu
sumber
2

Saya menulis solusi yang suka dan sering digunakan. Kode ini ada di http://code.google.com/p/pgutils/ . Lihat tampilan pgutils.foreign_keys.

Sayangnya, hasilnya terlalu bertele-tele untuk dimasukkan di sini. Namun, Anda dapat mencobanya di versi publik dari database di sini, seperti ini:

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

Ini bekerja dengan setidaknya 8,3. Saya mengantisipasi memperbaruinya, jika perlu, dalam beberapa bulan ke depan.

-Menerima

Reece
sumber
1
Tautan proyek sekarang mati.
pimlottc
@pimlottc: Pindah ke bitbucket.org/reece/pgutils . Terima kasih telah menunjukkan ini.
Reece
1

Saya membuat sedikit alat untuk query dan kemudian membandingkan skema basis data: Dump PostgreSQL db schema ke teks

Ada info tentang FK, tetapi respons ollyc memberikan rincian lebih lanjut.

Michał Niklas
sumber
0

Catatan: Jangan lupa urutan kolom saat membaca kolom kendala!

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

Ini adalah apa yang saya gunakan saat ini, itu akan mencantumkan tabel dan itu adalah batasan fkey [hapus tabel klausa dan akan mencantumkan semua tabel di katalog saat ini]:

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')
hajikelist
sumber
0

yang tercepat untuk memverifikasi jawaban langsung berdasarkan sepenuhnya pada jawaban ini

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"
Yordan Georgiev
sumber