J'ai une grande base de données dont j'ai besoin pour extraire toutes les clés primaires et clés étrangères de chaque table.
J'ai pgAdmin III.
Existe-t-il un moyen de le faire automatiquement et de ne pas parcourir chaque table manuellement?
Vous pouvez utiliser la fonction pg_get_constraintdef(constraint_oid)
dans une requête comme celle-ci:
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;
Résultat:
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
...
Renvoie toutes les clés primaires et étrangères pour toutes les tables du schéma donné, classées par nom de table, PK en premier.
Le manuel sur les types d'identifiant d'objet (regclass
, regnamespace
, ...) .
Basé sur la solution 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;
Renvoie une table de formulaire:
| FK_Table | FK_Column | PK_Table | PK_Column |
Pas besoin d'analyser pg_get_constraintdef()
, utilisez simplement les colonnes de pg_constraint
table pour obtenir d'autres détails ( la documentation ).
Ici constraint_type
peut être:
Basé sur réponse d'Erwin :
SELECT c.conname AS constraint_name,
c.contype AS constraint_type,
sch.nspname AS "self_schema",
tbl.relname AS "self_table",
ARRAY_AGG(col.attname ORDER BY u.attposition) AS "self_columns",
f_sch.nspname AS "foreign_schema",
f_tbl.relname AS "foreign_table",
ARRAY_AGG(f_col.attname ORDER BY f_u.attposition) AS "foreign_columns",
pg_get_constraintdef(c.oid) AS definition
FROM pg_constraint c
LEFT JOIN LATERAL UNNEST(c.conkey) WITH ORDINALITY AS u(attnum, attposition) ON TRUE
LEFT JOIN LATERAL UNNEST(c.confkey) WITH ORDINALITY AS f_u(attnum, attposition) ON f_u.attposition = u.attposition
JOIN pg_class tbl ON tbl.oid = c.conrelid
JOIN pg_namespace sch ON sch.oid = tbl.relnamespace
LEFT JOIN pg_attribute col ON (col.attrelid = tbl.oid AND col.attnum = u.attnum)
LEFT JOIN pg_class f_tbl ON f_tbl.oid = c.confrelid
LEFT JOIN pg_namespace f_sch ON f_sch.oid = f_tbl.relnamespace
LEFT JOIN pg_attribute f_col ON (f_col.attrelid = f_tbl.oid AND f_col.attnum = f_u.attnum)
GROUP BY constraint_name, constraint_type, "self_schema", "self_table", definition, "foreign_schema", "foreign_table"
ORDER BY "self_schema", "self_table";
Les résultats sont classés par schema
et table
.
Note technique: voir cette question à propos de with ordinality
.
J'ai récemment dû implémenter cela pour une couche d'accès aux données qui construit des utilitaires CRUD basés sur un schéma d'informations, a fini par aller avec cela.
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')