it-swarm.com.de

Wie erhalte ich die Primärschlüssel einer Tabelle von Postgres über plpgsql?

Wie extrahiere ich bei gegebenem Tabellennamen eine Liste der Primärschlüsselspalten und ihrer Datentypen aus einer plpgsql-Funktion?

33
jsight

Die obige Abfrage ist sehr schlecht, da sie sehr langsam ist.

Ich würde diese offizielle Version empfehlen:

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

wenn ein Schema benötigt wird, lautet die Abfrage wie folgt

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

Um ein wenig SQL bereitzustellen, können Sie die Primärschlüsselspalten und ihre Typen mit folgendem auflisten:

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

Schauen Sie sich die pg_constraint Systemtabelle an. Oder information_schema.table_constraints view, wenn Sie es vorziehen, nahe am SQL-Standard zu bleiben.

Um ein vollständiges Beispiel zu erhalten, verbinden Sie sich mit psql mit der Option "-E" mit einer Datenbank und geben Sie \d <some_table> ein - Sie sehen die eigentlichen Abfragen, die zur Beschreibung einer Tabelle verwendet werden.

5
Milen A. Radev

Die folgende SQL-Anweisung funktioniert für mich:

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;

Es wird direkt von hier genommen.

5
BullyWiiPlaza

Achten Sie auf Indizes, deren Spaltenreihenfolge sich von der Spaltenreihenfolge der Tabelle unterscheidet. (d. h. wenn der Primärschlüssel die Spalten 3, 2 und 1 verwendete)

Die folgende Abfrage ist viel komplexer, gibt jedoch die Spalten in der richtigen Reihenfolge zurück. (Entfernen Sie die "indisprimary" -Klausel, um die gleichen Informationen für alle Indizes einer Tabelle zu erhalten.)

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

Sie brauchen dafür wirklich nur 2 Systemtabellen:

  • pg_constraint - gibt an, welche Spalten (nach Nummer) zum Primärschlüssel gehören
  • pg_attribute - übersetzt die Spaltennummern in Spaltennamen

Hinweis: Die Systemtabellen können sich zwischen den PostgreSQL-Versionen ändern, dies kommt jedoch nicht häufig vor (tatsächlich sehr selten, wenn überhaupt). Und im Gegensatz zur Verwendung der information_schema.table_constraints benötigen Sie keine speziellen Berechtigungen. Wählen Sie einfach in der Tabelle aus. (Dies wurde in Postgres 10.6 getestet)

SELECT string_agg(a.attname, ', ') AS pk
FROM
    pg_constraint AS c
    CROSS JOIN LATERAL UNNEST(c.conkey) AS cols(colnum) -- conkey is a list of the columns of the constraint; so we split it into rows so that we can join all column numbers onto their names in pg_attribute
    INNER JOIN pg_attribute AS a ON a.attrelid = c.conrelid AND cols.colnum = a.attnum
WHERE
    c.contype = 'p' -- p = primary key constraint
    AND c.conrelid = '<schemaname>.<tablename>'::REGCLASS; -- regclass will type the name of the object to its internal oid
1
Joe Samanek
\d tablename 

sie erhalten die Primärschlüsselinformationen zusammen mit anderen tabellenbezogenen Informationen, wie z. B. allen Spalten, ihren Typen, zugeordneten Indizes, Einschränkungen, Regeln, Triggern usw. Sie benötigen wahrscheinlich nicht alle diese Informationen, aber dies ist der schnellste Weg, um alle zu erhalten Details auf einen Blick, sehen Sie mehr Details hier .

Es gibt so etwas zurück:

    Table "public.tablename"
     Column |  Type   | Modifiers 
    --------+---------+-----------
     col1   | text    | not null
     col2   | numeric | 
     col3   | text    | 
     col4   | text    | 
     col5   | numeric | 
    Indexes:
        "tablename_pkey" PRIMARY KEY, btree (col1)
0
Konrad
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

Spaltenreihenfolge beibehalten mit 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