Dato un nome di tabella, come faccio a estrarre un elenco di colonne chiave primarie e i relativi tipi di dati da una funzione plpgsql?Come ottengo la chiave primaria (s) di una tabella da Postgres via plpgsql?
risposta
La query sopra è molto male come è molto lento.
consiglio questo versione ufficiale:
http://wiki.postgresql.org/wiki/Retrieve_primary_key_columns
se è necessario lo schema della query è la seguente
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
Dai un'occhiata alla tabella di sistema pg_constraint
. O vista information_schema.table_constraints
se si preferisce rimanere vicini allo standard SQL.
Per un esempio completo, connettersi a un DB utilizzando psql
con l'opzione "-E" e digitare \d <some_table>
- verranno visualizzate le query effettive utilizzate nella descrizione di una tabella.
Inoltre, combina questo con i dati di pg_indexes e dovresti essere abbastanza buono. In realtà una chiave primaria è solo un indice univoco con non null su tutti i campi. –
Per fornire un po 'dritto di SQL, è possibile elencare le colonne chiave primaria e le loro tipologie con:
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';
Quando lo eseguo sul mio server Postgres, ottengo un set di risultati vuoto. Prima di chiedere, ho sostituito ''mytable'' con il nome corretto del tavolo. Devo essere in uno specifico contesto o ambito per far funzionare tutto questo? – 2mac
Beware of indici in cui l'ordine delle colonne è diverso da ordine delle colonne della tabella. (Ad esempio, se la chiave primaria utilizzava le colonne 3, 2 e 1)
La seguente query è molto più complessa, ma restituisce le colonne nell'ordine corretto. (Rimuovere la clausola 'indisprimary' per ottenere le stesse informazioni per tutti gli indici su un tavolo)
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
Preservare l'ordine delle colonne utilizzando 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
Le seguenti SQL
dichiarazioni funziona per me:
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;
Viene preso direttamente da here.
Sono abbastanza sicuro che non è necessario unirsi a pg_namespace. L'oid di pg_class è univoco, quindi quando lo lanci su una regclass stai già implicando il nome dello schema. Se hai bisogno del nome dello schema, includilo nel nome della tabella: 'public.foo' :: regclass. –
"La query sopra è pessima in quanto è molto lenta." Si prega di evitare di fare riferimento alla posizione relativa sulla pagina di altre risposte in quanto questo cambia nel tempo e dal metodo di ordinamento selezionato. Invece il modo più a prova di futuro di riferirsi a un'altra risposta è collegarlo ad esso. – faintsignal