web-dev-qa-db-fra.com

Comment obtenir les clés primaires d'une table auprès de Postgres via plpgsql?

Étant donné un nom de table, comment extraire une liste de colonnes de clé primaire et leurs types de données à partir d'une fonction plpgsql?

33
jsight

La requête ci-dessus est très mauvaise car elle est vraiment lente.

Je recommanderais cette version officielle:

http://wiki.postgresql.org/wiki/Retrieve_primary_key_columns

si un schéma est nécessaire, la requête est la suivante

SELECT               
  pg_attribute.attname, 
  format_type(pg_attribute.atttypid, pg_attribute.atttypmod) 
FROM pg_index, pg_class, pg_attribute, pg_namespace 
WHERE 
  pg_class.oid = 'foo'::regclass AND 
  indrelid = pg_class.oid AND 
  nspname = 'public' AND 
  pg_class.relnamespace = pg_namespace.oid AND 
  pg_attribute.attrelid = pg_class.oid AND 
  pg_attribute.attnum = any(pg_index.indkey)
 AND indisprimary
26
user3094383

Pour fournir un peu de SQL, vous pouvez lister les colonnes de clé primaire et leurs types avec:

SELECT c.column_name, c.data_type
FROM information_schema.table_constraints tc 
JOIN information_schema.constraint_column_usage AS ccu USING (constraint_schema, constraint_name) 
JOIN information_schema.columns AS c ON c.table_schema = tc.constraint_schema
  AND tc.table_name = c.table_name AND ccu.column_name = c.column_name
WHERE constraint_type = 'PRIMARY KEY' and tc.table_name = 'mytable';
16
Jamie Love

Jetez un coup d'œil à pg_constraint table système. Ou information_schema.table_constraints view si vous préférez rester proche du standard SQL.

Pour un exemple complet, connectez-vous à une base de données à l'aide de psql avec l'option "-E" et tapez \d <some_table>. Les requêtes utilisées pour décrire une table sont affichées.

5
Milen A. Radev

L'instruction SQL suivante fonctionne pour moi:

SELECT a.attname
FROM   pg_index i
JOIN   pg_attribute a ON a.attrelid = i.indrelid
                     AND a.attnum = ANY(i.indkey)
WHERE  i.indrelid = 'tablename'::regclass
AND    i.indisprimary;

Il est directement pris de ici .

5
BullyWiiPlaza

Méfiez-vous des index où l'ordre des colonnes diffère de l'ordre des colonnes de la table. (c'est-à-dire si la clé primaire utilisait les colonnes 3, 2 et 1)

La requête suivante est beaucoup plus complexe, mais renvoie les colonnes dans le bon ordre. (Supprimez la clause 'indisprimary' pour obtenir les mêmes informations pour tous les index d'une table)

WITH ndx_list AS
(
    SELECT pg_index.indexrelid
      FROM pg_index, pg_class
     WHERE pg_class.relname = 'test_indices_table'
       AND pg_class.oid = pg_index.indrelid
       AND pg_index.indisprimary
), ndx_cols AS
(
   SELECT pg_class.relname AS index_name, UNNEST(i.indkey) AS col_ndx, i.indisunique, i.indisprimary
     FROM pg_class, pg_index i
    WHERE pg_class.oid = i.indexrelid
      AND pg_class.oid IN (SELECT indexrelid FROM ndx_list)
)
  SELECT ndx_cols.index_name, ndx_cols.indisunique, ndx_cols.indisprimary,
         a.attname, format_type(a.atttypid, a.atttypmod), a.attnum
    FROM pg_class c, pg_attribute a
    JOIN ndx_cols ON (a.attnum = ndx_cols.col_ndx)
   WHERE c.oid = 'test_indices_table'::regclass
     AND a.attrelid = c.oid
1
jamesvl
SELECT
   conrelid::regclass AS table_from,
   conname,
   pg_get_constraintdef ( c.oid )
FROM
   pg_constraint c
   JOIN pg_namespace n ON n.oid = c.connamespace
WHERE
   contype IN ( 'f', 'p ' )
   AND conrelid::regclass::TEXT IN ( 'foo' )

ORDER BY
   conrelid::regclass::TEXT,
   contype DESC
0
user2553316 Ns

Préserver l'ordre des colonnes à l'aide de generate_subscripts :

SELECT
  a.attname,
  format_type(a.atttypid, a.atttypmod) 
FROM
  pg_attribute a
  JOIN (SELECT *, GENERATE_SUBSCRIPTS(indkey, 1) AS indkey_subscript FROM pg_index) AS i
    ON
      i.indisprimary
      AND i.indrelid = a.attrelid
      AND a.attnum = i.indkey[i.indkey_subscript]
WHERE
  a.attrelid = 'your_table'::regclass
ORDER BY
  i.indkey_subscript
0
snipsnipsnip