Tôi có một cơ sở dữ liệu lớn mà tôi cần trích xuất tất cả các khóa chính và khóa ngoại từ mỗi bảng.
Tôi có pgAdmin III.
Có cách nào để làm điều này tự động và không đi qua từng bảng một cách thủ công không?
Tôi có một cơ sở dữ liệu lớn mà tôi cần trích xuất tất cả các khóa chính và khóa ngoại từ mỗi bảng.
Tôi có pgAdmin III.
Có cách nào để làm điều này tự động và không đi qua từng bảng một cách thủ công không?
Câu trả lời:
Bạn có thể sử dụng hàm pg_get_constraintdef(constraint_oid)trong một truy vấn như sau:
SELECT conrelid::regclass AS table_from
     , conname
     , pg_get_constraintdef(oid)
FROM   pg_constraint
WHERE  contype IN ('f', 'p ')
AND    connamespace = 'public'::regnamespace  -- your schema here
ORDER  BY conrelid::regclass::text, contype DESC;Kết quả:
 table_from | conname    | pg_get_constraintdef
------------+------------+----------------------
 tbl        | tbl_pkey   | PRIMARY KEY (tbl_id)
 tbl        | tbl_col_fk | FOREIGN KEY (col) REFERENCES tbl2(col) ON UPDATE CASCADE
...Trả về tất cả các khóa chính và khóa ngoài cho tất cả các bảng trong lược đồ đã cho, được sắp xếp theo tablename, PK trước.
Tài liệu hướng dẫn về các loại định danh đối tượng ( regclass, regnamespace, ...).
Dựa trên giải pháp Erwin:
SELECT conrelid::regclass AS "FK_Table"
      ,CASE WHEN pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %' THEN substring(pg_get_constraintdef(c.oid), 14, position(')' in pg_get_constraintdef(c.oid))-14) END AS "FK_Column"
      ,CASE WHEN pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %' THEN substring(pg_get_constraintdef(c.oid), position(' REFERENCES ' in pg_get_constraintdef(c.oid))+12, position('(' in substring(pg_get_constraintdef(c.oid), 14))-position(' REFERENCES ' in pg_get_constraintdef(c.oid))+1) END AS "PK_Table"
      ,CASE WHEN pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %' THEN substring(pg_get_constraintdef(c.oid), position('(' in substring(pg_get_constraintdef(c.oid), 14))+14, position(')' in substring(pg_get_constraintdef(c.oid), position('(' in substring(pg_get_constraintdef(c.oid), 14))+14))-1) END AS "PK_Column"
FROM   pg_constraint c
JOIN   pg_namespace n ON n.oid = c.connamespace
WHERE  contype IN ('f', 'p ')
AND pg_get_constraintdef(c.oid) LIKE 'FOREIGN KEY %'
ORDER  BY pg_get_constraintdef(c.oid), conrelid::regclass::text, contype DESC;Sẽ trả về một bảng biểu mẫu:
| FK_Table | FK_Column | PK_Table | PK_Column |Không cần phân tích cú pháp pg_get_constraintdef(), chỉ cần sử dụng các cột của pg_constraintbảng để có được các chi tiết khác ( các tài liệu ).
Đây constraint_typecó thể là:
Dựa trên câu trả lời của Erwin :
SELECT c.conname                                     AS constraint_name,
       c.contype                                     AS constraint_type,
       sch.nspname                                   AS "schema",
       tbl.relname                                   AS "table",
       ARRAY_AGG(col.attname ORDER BY u.attposition) AS columns,
       pg_get_constraintdef(c.oid)                   AS definition
FROM pg_constraint c
       JOIN LATERAL UNNEST(c.conkey) WITH ORDINALITY AS u(attnum, attposition) ON TRUE
       JOIN pg_class tbl ON tbl.oid = c.conrelid
       JOIN pg_namespace sch ON sch.oid = tbl.relnamespace
       JOIN pg_attribute col ON (col.attrelid = tbl.oid AND col.attnum = u.attnum)
GROUP BY constraint_name, constraint_type, "schema", "table", definition
ORDER BY "schema", "table";Kết quả được sắp xếp theo schemavà table.
Lưu ý kỹ thuật: xem câu hỏi này về with ordinality.
Gần đây đã phải thực hiện điều này cho Lớp truy cập dữ liệu xây dựng các tiện ích CRUD dựa trên lược đồ thông tin, kết thúc với việc này.
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
    "pg_constraint".contype IN ( 'f', 'p' )
    AND
    "pg_namespace".nspname = current_schema()
    AND
    "pg_constraint".conrelid::regclass::text IN ('whatever_table_name')
WHERE contype IN ('f', 'p', 'u')