Postgres: SQL để liệt kê các khóa ngoại bảng


219

Có cách nào sử dụng SQL để liệt kê tất cả các khóa ngoại cho một bảng đã cho không? Tôi biết tên bảng / lược đồ và tôi có thể cắm nó vào.


Tôi đề nghị sử dụng câu trả lời của @Magnus . Đơn giản nhất, sạch sẽ nhất, nhanh nhất.
Erwin Brandstetter

Câu trả lời:


373

Bạn có thể làm điều này thông qua các bảng information_schema. Ví dụ:

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' nên là tc.table_name = 'mytable' hoặc nếu không, nó sẽ gây ra một lỗi mơ hồ
intrepion

15
+1, rất hữu ích. Để làm cho truy vấn mạnh mẽ hơn, có lẽ nó cũng nên tham gia vào ràng buộc, vì hai lược đồ có thể có các ràng buộc có cùng tên. Một cái gì đó như: 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
Điều này phá vỡ khi có một số cột trong một ràng buộc, phải không? Dường như không có cách thích hợp để liên kết các cột pk với các cột fk bằng information_schema BTW.
fionbio

5
Nó thực sự phá vỡ với nhiều hơn một cột trong ràng buộc. Đối với Postgres, có một cách để lấy thông tin này từ lược đồ pg_catalog. Xem câu trả lời của tôi dưới đây.
martin

9
Truy vấn sai. Nó giả định rằng các tên ràng buộc không thể lặp lại, đó là sai. Các ràng buộc có cùng tên có thể tồn tại trong các không gian tên khác nhau. Bạn đang sử dụng ràng buộc để tham gia. Đồng thời tham gia vào cả ràng buộc tên và tên lược đồ sẽ không hoạt động vì bạn không chắc chắn hai ràng buộc này giống nhau. Tùy chọn duy nhất là sử dụng pg_constraint, pg_group, v.v. bằng cách sử dụng oids để tham gia. Danh mục ANSI của Postgres chỉ có ở đó để tuân thủ nhưng nó còn thiếu sót. pg_catalog là con đường để đi. Câu trả lời đúng là ở đây dba.stackexchange.com/questions/36979/retrieving-all-pk-and-fk
Tulains Córdova

69

psql thực hiện điều này và nếu bạn bắt đầu psql với:

psql -E

nó sẽ cho bạn thấy chính xác những gì truy vấn được thực hiện. Trong trường hợp tìm khóa ngoại, đó là:

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

Trong trường hợp này, 16485 là ô vuông của bảng mà tôi đang xem - bạn có thể lấy cái đó bằng cách chỉ cần chọn tablename của mình để phân loại lại như sau:

WHERE r.conrelid = 'mytable'::regclass

Lược đồ đủ điều kiện tên bảng nếu nó không phải là duy nhất (hoặc tên đầu tiên trong của bạn search_path):

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

2
Điều này rất tiện dụng! Postgres dường như có một triệu chức năng nhỏ như thế này giúp mọi thứ đơn giản hơn. Bây giờ làm thế nào để nhớ chúng?
epic_fil 6/214

5
@Phil: Bạn chỉ cần một ý tưởng chung. Hãy để hướng dẫn ghi nhớ phần còn lại.
Erwin Brandstetter

3
để liệt kê tất cả các khóa ngoại nhắm vào bảng: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 tôi phải làm thế nào để có được tên bảng nước ngoài?
Wellington Silva Ribeiro

2
Tôi không hiểu, nên sử dụng lệnh nào? psql -E -U username -d database ThenWHAT?
Poutrathor

49

Vấn đề \d+ tablenamevề lời nhắc của PostgreSQL, ngoài việc hiển thị các kiểu dữ liệu của cột trong bảng, nó sẽ hiển thị các chỉ mục và khóa ngoại.


Xin lỗi đã không nhận thấy bình luận của tôi đã bị cắt. Nếu bạn ít nhất có thể thử nó một lần, bạn sẽ thấy ánh xạ khóa ngoại cũng được hiển thị.
Gre Hahn

45

Câu trả lời của Ollyc là tốt vì nó không dành riêng cho Postgres, tuy nhiên, nó bị hỏng khi khóa ngoại tham chiếu nhiều hơn một cột. Truy vấn sau đây hoạt động với số lượng cột tùy ý nhưng nó phụ thuộc rất nhiều vào các tiện ích mở rộng 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

trước 8.4, chức năng không nhất thiết phải được tạo lúc đầu. wiki.postgresql.org/wiki/Array_Unnest
maletin

Trường hợp nào người ta chèn tên bảng vào truy vấn này? Đã nhập nguyên văn ở trên trả về 0 hàng trên DB PSQL của tôi có hàng chục khóa ngoại.
Phrogz

4
Bạn thay thế 'child_table' và 'child_schema' bằng tên của bảng và lược đồ của nó
martin

Điều này không cho bạn biết tên của fkey.
Evan Carroll

@EvanCarroll Tôi đã cập nhật câu trả lời của mình để bao gồm tên của khóa.
martin

31

Mở rộng cho công thức 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';

Sau đó:

SELECT * FROM foreign_keys_view WHERE table_name='YourTableNameHere';


Cảm ơn, lý tưởng cho việc tái sử dụng.
schellingerht

16

kiểm tra bài đăng ff cho giải pháp của bạn và đừng quên đánh dấu bài này khi bạn thấy điều này hữu ích

http://errorbank.blogspot.com/2011/03/list-all-forign-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');

Cung cấp hai SQL hoạt động trên PostgreQuery 9.1 (một khi bạn sửa lỗi thoát sai, hãy đặt 'tablename' (không có tiền tố lược đồ) vào SQL).
alfonx

2
+1: đây là giải pháp duy nhất không trả về các bản sao.
Olivier MATROT

với giải pháp này, hoạt động tốt và không trả lại trùng lặp.
Fuhrmann

1
Giải pháp này sẽ chỉ hiển thị cột đầu tiên của bất kỳ khóa ngoại nhiều cột nào ... nhưng trông đơn giản hơn nhiều so với cột tôi vừa đăng sẽ thực hiện bội số.
dewin

12

Truy vấn này hoạt động chính xác với các khóa tổng hợp cũng:

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
Bạn đang tham gia các cột trên "ràng buộc", do đó, điều này sẽ chỉ hoạt động nếu tất cả các tên ràng buộc của bạn là duy nhất (trên tất cả các bảng trong tất cả các lược đồ). Điều này thường không phải là một yêu cầu và do đó không được cơ sở dữ liệu thực thi.
Zilk

3
Cảm ơn. Đây là câu trả lời duy nhất cho thấy cách sử dụng information_schema để xử lý đúng nhiều cột.
Samuel Danielson

Giải pháp này hoạt động. Nó không tạo ra các bản sao và nó xử lý nhiều trường trong FK.
Igor

9

Tôi nghĩ những gì bạn đang tìm kiếm và rất gần với những gì @ollyc đã viết là:

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

Điều này sẽ liệt kê tất cả các bảng sử dụng bảng được chỉ định của bạn làm khóa ngoại


9

upvote ngắn nhưng ngọt ngào nếu nó làm việc cho bạn.

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

Làm việc say mê khi tôi viết với PG 12.2
Jack Kinsella

5

Không có câu trả lời nào hiện có cho tôi kết quả ở dạng mà tôi thực sự muốn chúng. Vì vậy, đây là truy vấn (gargantuan) của tôi để tìm thông tin về khóa ngoại.

Một vài lưu ý:

  • Các biểu thức được sử dụng để tạo from_colsto_colscó thể được đơn giản hóa rất nhiều trên Postgres 9.4 trở lên bằng cách sử dụng WITH ORDINALITYchứ không phải là hackery sử dụng chức năng cửa sổ mà tôi đang sử dụng.
  • Những biểu thức tương tự đang dựa vào trình hoạch định truy vấn không làm thay đổi thứ tự kết quả được trả về từ đó UNNEST. Tôi không nghĩ nó sẽ như vậy, nhưng tôi không có bất kỳ khóa ngoại nào có nhiều cột trong tập dữ liệu của mình để kiểm tra. Thêm 9,4 niceties loại bỏ khả năng này hoàn toàn.
  • Bản thân truy vấn yêu cầu Postgres 9.0 trở lên (8.x không cho phép ORDER BYtrong các hàm tổng hợp)
  • Thay thế STRING_AGGbằng ARRAY_AGGnếu bạn muốn một mảng các cột thay vì một chuỗi được phân tách bằng dấu phẩy.

-

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

Một cách khác:

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

Sử dụng tên của Khóa chính mà Khóa đang tham chiếu và truy vấn information_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')

Ở đây 'TABLE_NAME_pkey' là tên của Khóa chính được tham chiếu bởi Khóa ngoại.


4

Đây là một giải pháp của Andreas Joseph Krogh từ danh sách gửi thư của PostgreSQL: 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;

Giải pháp này xử lý các khóa ngoại tham chiếu nhiều cột và tránh trùng lặp (điều mà một số câu trả lời khác không thực hiện được). Điều duy nhất tôi thay đổi là tên biến.

Dưới đây là một ví dụ trả về tất cả employeecác cột tham chiếu permissionbảng:

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

4

Để mở rộng câu trả lời xuất sắc của Martin ở đây là một truy vấn cho phép bạn lọc dựa trên bảng cha và hiển thị cho bạn tên của bảng con với mỗi bảng cha để bạn có thể thấy tất cả các bảng / cột phụ thuộc dựa trên các ràng buộc khóa ngoài trong bảng cha mẹ.

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
Truy vấn trong câu trả lời được chấp nhận thêm 1,2 giây vào truy vấn ~ 0,03, truy vấn của bạn chỉ thêm 0,01, cảm ơn!
Lập trình viên

3

Giải pháp phù hợp cho vấn đề, sử dụng information_schema, làm việc với các phím nhiều cột, nối các cột có tên khác nhau trong cả hai bảng một cách chính xác và cũng tương thích với 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

Lưu ý: Có một số khác biệt giữa các triển khai potgresql và sqlserver, trong information_schemađó làm cho câu trả lời hàng đầu cho kết quả khác nhau trên hai hệ thống - một hiển thị tên cột cho bảng khóa ngoại khác cho bảng khóa chính. Vì lý do này, tôi đã quyết định sử dụng chế độ xem KEY_COLUMN_USAGE thay thế.


Lược đồ thông tin có vẻ như là câu trả lời đúng, nhưng thực sự bạn muốn các bảng pg_catalog: pg_constraint, v.v. Chúng tôi đã bị cắn mạnh bởi điều này. nếu cơ sở dữ liệu của bạn có số lượng lớn các ràng buộc thì có thể có vấn đề về hiệu suất ...
hajikelist 16/03/18

Điều kiện trên ORDINAL_POSITIONcó thể mang lại kết quả không chính xác khi thứ tự các cột trong khóa ngoài khác với thứ tự các cột trong ràng buộc duy nhất. Tôi tin rằng bạn nên đã tham gia vào kcu_foreign.POSITION_IN_UNIQUE_CONSTRAINT = kcu_primary.ORDINAL_POSITION Cập nhật : Ngoài ra, một chìa khóa nước ngoài có thể phụ thuộc vào một hạn chế UNIQUE là tốt, vì vậy tôi nghĩ rằng bạn nên loại bỏ các pks.CONSTRAINT_TYPEđiều kiện và chỉ có thể tham gia rcđể kcu_primarytrực tiếp
easd

Tôi đã thực hiện một câu trả lời tương tự ở đây: 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

2

Tôi đã viết một giải pháp thích và sử dụng thường xuyên. Mã này có tại http://code.google.com.vn/p/pgutils/ . Xem chế độ xem pgutils.forign_keys.

Thật không may, đầu ra quá dài để bao gồm ở đây. Tuy nhiên, bạn có thể dùng thử trên phiên bản công khai của cơ sở dữ liệu tại đây, như thế này:

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

Điều này hoạt động với ít nhất 8.3. Tôi dự đoán sẽ cập nhật nó, nếu cần, trong vài tháng tới.

-Reece


1
Liên kết dự án hiện đã chết.
pimlottc

@pimlottc: Đã chuyển sang bitbucket.org/reece/pgutils . Cảm ơn đã chỉ ra điều này.
lừa


0

Lưu ý: Đừng quên thứ tự của cột trong khi đọc các cột ràng buộc!

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

Đây là những gì tôi hiện đang sử dụng, nó sẽ liệt kê một bảng và đó là các ràng buộc fkey [loại bỏ mệnh đề bảng và nó sẽ liệt kê tất cả các bảng trong danh mục hiện tại]:

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

nhanh nhất để xác minh thẳng trong câu trả lời bash hoàn toàn dựa trên câu trả lời này

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"
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.