Bagaimana cara menentukan apakah kolom didefinisikan sebagai tipe data serial dan bukan bilangan bulat berdasarkan katalog?

9

Jadi saya sedang membuat beberapa SQL untuk membaca postgres (9.1) katalog untuk membangun definisi tabel. Namun, saya mengalami masalah dengan tipe data SERIAL / BIGSERIAL.

Contoh:

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"

Ini memberi saya nama database (db), nama skema (cruft), nama tabel (temp), nama kolom (id), nilai default (nextval (...)), dan tipe data (bigint dan int8 .. BUKAN bigserial) ... Saya menyadari bahwa saya hanya bisa memeriksa untuk melihat apakah nilai default adalah urutan - tetapi saya tidak percaya itu akan 100% akurat karena saya bisa secara manual membuat urutan dan membuat kolom non serial di mana nilai defaultnya adalah urutan itu.

Adakah yang punya saran untuk bagaimana saya bisa mencapai ini? Apa pun selain memeriksa nilai default untuk nextval (* _ seq)?

Diedit untuk solusi SQL yang ditambahkan di sini dalam kasus TL; DR atau pengguna baru yang tidak terbiasa dengan 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;
Joishi Bodio
sumber
1
Kemudian, jawaban terkait dengan contoh kode: dba.stackexchange.com/questions/90555/…
Erwin Brandstetter

Jawaban:

8

SERIAL dan BIGSERIAL adalah jenis pseudo-type. Seperti yang Anda perhatikan, mereka benar-benar hanya INT dan BIGINT secara internal.

Apa yang terjadi di balik layar adalah PostgreSQL membuat urutan dan mengatur ketergantungannya ke tabel. Anda dapat mencari pg_class untuk nama urutan dan bagaimana hubungannya dengan tabel.

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

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

Fungsi Urutan: http://www.postgresql.org/docs/9.2/static/functions- berikutnyaence.html

Posting StackOverflow ini mungkin membantu: /programming/1493262/list-all-afterences-in-a-postgres-db-8-1-with-sql

UPDATE : Anda juga dapat menggunakan pg_depend untuk mengetahui urutan mana yang berhubungan dengan tabel / kolom yang Anda minati: http://www.postgresql.org/docs/9.2/static/catalog-pg-depend.html

efesar
sumber
10

Biarkan saya tambahkan ke jawaban efesar bahwa dokumentasi menyatakan sebagai berikut:

Tipe data smallserial, serial, dan bigserial bukan tipe yang benar, tetapi hanya kenyamanan notasi untuk membuat kolom pengidentifikasi unik (mirip dengan properti AUTO_INCREMENT yang didukung oleh beberapa database lain). Dalam implementasi saat ini, tentukan:

CREATE TABLE tablename (
    colname SERIAL
);

setara dengan menentukan:

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;

Yang berarti kalau

  • tipe data kolom adalah integer (bigint) dan
  • itu BUKAN NULL dan
  • nilai defaultnya berasal dari urutan yang dimiliki oleh kolom yang dimaksud

maka itu adalah serialkolom. Jadi memeriksa faktor-faktor ini dalam katalog, seperti yang Anda usulkan (dengan tambahan NOT NULL), cukup untuk mengidentifikasi serialkolom.

Untuk kueri aktual untuk menemukan serial (besar), lihat jawaban sempurna Erwin Brandstetter.

dezso
sumber