Wie bestimme ich, ob eine Spalte als serieller Datentyp anstelle einer Ganzzahl basierend auf dem Katalog definiert ist?

9

Daher erstelle ich derzeit SQL, um die Postgres (9.1) -Kataloge zu lesen und Tabellendefinitionen zu erstellen. Ich habe jedoch ein Problem mit den Datentypen SERIAL / BIGSERIAL.

Beispiel:

CREATE TABLE cruft.temp ( id BIGSERIAL PRIMARY KEY );
SELECT * FROM information_schema.columns WHERE table_schema='cruft' AND table_name='temp';
"db","cruft","temp","id",1,"nextval('cruft.temp_id_seq'::regclass)","NO","bigint",,,64,2,0,,,,,,,,,,,,,"db","pg_catalog","int8",,,,,"1","NO","NO",,,,,,,"NEVER",,"YES"

Es gibt mir den Datenbanknamen (db), den Schemanamen (cruft), den Tabellennamen (temp), den Spaltennamen (id), den Standardwert (nextval (...)) und den Datentyp (bigint und int8 .. NOT bigserial). ... Mir ist klar, dass ich nur überprüfen konnte, ob der Standardwert eine Sequenz war - aber ich glaube nicht, dass dies 100% genau wäre, da ich manuell eine Sequenz erstellen und eine nicht serielle Spalte erstellen könnte, in der der Standardwert war diese Sequenz.

Hat jemand einen Vorschlag, wie ich das erreichen könnte? Sonst noch etwas anderes als den Standardwert für einen nächsten Wert (* _ seq) zu überprüfen?

Bearbeitet für SQL-Lösung hier hinzugefügt im Fall von TL; DR oder neuen Benutzern, die mit dem pg_catalog nicht vertraut sind:

with sequences as (
  select oid, relname as sequencename from pg_class where relkind = 'S'
) select
  sch.nspname as schemaname, tab.relname as tablename, col.attname as columnname, col.attnum as columnnumber, seqs.sequencename
from pg_attribute col
join pg_class tab on col.attrelid = tab.oid
join pg_namespace sch on tab.relnamespace = sch.oid
left join pg_attrdef def on tab.oid = def.adrelid and col.attnum = def.adnum
left join pg_depend deps on def.oid = deps.objid and deps.deptype = 'n'
left join sequences seqs on deps.refobjid = seqs.oid
where sch.nspname != 'information_schema' and sch.nspname not like 'pg_%' -- won't work if you have user schemas matching pg_
  and col.attnum > 0
  and seqs.sequencename is not null -- TO ONLY VIEW SERIAL/BIGSERIAL COLUMNS
order by sch.nspname, tab.relname, col.attnum;
Joishi Bodio
quelle
1
Später verwandte Antwort mit Codebeispielen: dba.stackexchange.com/questions/90555/…
Erwin Brandstetter

Antworten:

8

SERIAL und BIGSERIAL sind Pseudotypen. Wie Sie bemerkt haben, sind sie intern nur INT und BIGINT .

Was hinter den Kulissen passiert, ist, dass PostgreSQL eine Sequenz erstellt und eine Abhängigkeit davon von der Tabelle herstellt. Sie können pg_class nach dem Sequenznamen und seiner Beziehung zur Tabelle durchsuchen .

pg_class: http://www.postgresql.org/docs/9.2/static/catalog-pg-class.html

SQL Fiddle: http://sqlfiddle.com/#!12/dfcbd/6

Sequenzfunktionen: http://www.postgresql.org/docs/9.2/static/functions-sequence.html

Dieser StackOverflow-Beitrag könnte hilfreich sein: /programming/1493262/list-all-sequences-in-a-postgres-db-8-1-with-sql

UPDATE : Sie können auch pg_depend verwenden, um herauszufinden, welche Sequenzen sich auf die Tabelle / Spalte beziehen, an der Sie interessiert sind: http://www.postgresql.org/docs/9.2/static/catalog-pg-depend.html

efesar
quelle
10

Lassen Sie mich zu Efesars Antwort hinzufügen, dass in der Dokumentation Folgendes angegeben ist:

Die Datentypen smallserial, serial und bigserial sind keine echten Typen, sondern lediglich eine Annehmlichkeit zum Erstellen eindeutiger Bezeichnerspalten (ähnlich der von einigen anderen Datenbanken unterstützten Eigenschaft AUTO_INCREMENT). In der aktuellen Implementierung wird Folgendes angegeben:

CREATE TABLE tablename (
    colname SERIAL
);

entspricht der Angabe von:

CREATE SEQUENCE tablename_colname_seq;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

Was bedeutet, dass wenn

  • Der Datentyp einer Spalte ist Integer (Bigint) und
  • es ist NICHT NULL und
  • Der Standardwert stammt aus einer Sequenz, die der betreffenden Spalte gehört

dann ist es eine serialSpalte. Die Überprüfung dieser Faktoren in den Katalogen, wie Sie vorgeschlagen haben (mit dem Zusatz von NOT NULL), reicht also aus, um eine serialSpalte zu identifizieren .

Eine aktuelle Abfrage zum Auffinden der (großen) Serien finden Sie in der ausgezeichneten Antwort von Erwin Brandstetter.

dezso
quelle