Récupération de tous les PK et FK

18

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?

Nick Ginanto
la source

Réponses:

29

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 pg_constraint.

Le manuel sur les types d'identificateur d'objet ( regclass, regnamespace, ...).

Erwin Brandstetter
la source
1
Cela a modifié où la condition renvoie également toutes les contraintes uniques:WHERE contype IN ('f', 'p', 'u')
Daniel Waltrip
8

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 |
profimedica
la source
4

Pas besoin d'analyser pg_get_constraintdef(), utilisez simplement les colonnes du pg_constrainttableau pour obtenir d' autres détails ( les documents ).

Voici constraint_typepeut être:

  • p - clé primaire ,
  • f - clé étrangère ,
  • u - unique ,
  • c - vérifier la contrainte ,
  • x - exclusion ,
  • ...

D'après la réponse d'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";

Les résultats sont classés par schemaet table.

Note technique: voir cette question sur with ordinality.

Evgeny Nozdrev
la source
1

J'ai récemment dû l'implémenter 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')
hajikelist
la source