Así que actualmente estoy creando algunos SQL para leer los catálogos de postgres (9.1) para construir definiciones de tabla. Sin embargo, me encuentro con un problema con los tipos de datos SERIAL / BIGSERIAL.
Ejemplo:
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"
Me da el nombre de la base de datos (db), el nombre del esquema (cruft), el nombre de la tabla (temp), el nombre de la columna (id), el valor predeterminado (nextval (...)) y el tipo de datos (bigint e int8 ... NO bigserial) ... Me doy cuenta de que podría verificar si el valor predeterminado era una secuencia, pero no creo que sea 100% preciso ya que podría crear manualmente una secuencia y crear una columna no serial donde el valor predeterminado era esa secuencia
¿Alguien tiene alguna sugerencia sobre cómo podría lograr esto? ¿Algo más que verificar el valor predeterminado para un nextval (* _ seq)?
Editado para la solución SQL agregada aquí en caso de TL; DR o nuevos usuarios que no están familiarizados con el pg_catalog:
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;
fuente
Respuestas:
SERIAL y BIGSERIAL son una especie de pseudo-tipos. Como notó, en realidad son solo INT y BIGINT internamente.
Lo que sucede detrás de escena es que PostgreSQL crea una secuencia y establece una dependencia en la tabla. Puede buscar pg_class para el nombre de secuencia y cómo se relaciona con la tabla.
pg_class: http://www.postgresql.org/docs/9.2/static/catalog-pg-class.html
Fiddle de SQL: http://sqlfiddle.com/#!12/dfcbd/6
Funciones de secuencia: http://www.postgresql.org/docs/9.2/static/functions-sequence.html
Esta publicación de StackOverflow puede ser útil: /programming/1493262/list-all-sequences-in-a-postgres-db-8-1-with-sql
ACTUALIZACIÓN : También puede usar pg_depend para averiguar qué secuencias se relacionan con la tabla / columna que le interesa: http://www.postgresql.org/docs/9.2/static/catalog-pg-depend.html
fuente
Permítanme agregar a la respuesta de efesar que la documentación establece lo siguiente:
Lo que significa que si
entonces es una
serial
columna. Por lo tanto, verificar estos factores en los catálogos, como propuso (con la adición deNOT NULL
), es suficiente para identificar unaserial
columna.Para una consulta real para encontrar las series (grandes), vea la excelente respuesta de Erwin Brandstetter.
fuente