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_constraint
bảng để có được các chi tiết khác ( các tài liệu ).
Đây constraint_type
có 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 schema
và 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')