Dua minggu setelah membuat tabel, wajar kalau ingatan kita kabur: apa saja kolomnya, kolom mana yang wajib diisi, apa nilainya default? Untunglah PostgreSQL tidak pernah lupa — setiap definisi tabel yang kita buat tercatat rapi di dalam server, dan ada tiga pintu untuk membacanya kembali: meta-command psql seperti \d, view standar information_schema, dan system catalog pg_catalog. Pada chapter ini kita memakai ketiganya di atas satu tabel yang sama dan membandingkan kapan masing-masing pintu paling tepat dipakai.
Menyiapkan Tabel untuk Diamati #
Tabel latihan kita adalah pelanggan dari chapter sebelumnya — cukup kaya untuk memperlihatkan semua informasi yang menarik (primary key, NOT NULL, UNIQUE, dan DEFAULT), tetapi tetap ringkas:
CREATE TABLE pelanggan (
id integer PRIMARY KEY,
nama text NOT NULL,
email text UNIQUE,
kota text DEFAULT 'Jakarta'
);
INSERT INTO pelanggan (id, nama, email)
VALUES (1, 'Budi', '[email protected]');Output yang Dihasilkan:
CREATE TABLE
INSERT 0 1Meta-Command psql: \dt dan \d #
Cara tercepat memeriksa struktur adalah meta-command — perintah yang diawali backslash dan diproses oleh psql sendiri, bukan dikirim ke server sebagai SQL. \dt mendaftar semua tabel dalam search_path, sedangkan \d nama_tabel membedah satu tabel sampai ke constraint-nya:
\dt
\d pelangganOutput yang Dihasilkan:
List of relations
Schema | Name | Type | Owner
--------+-----------+-------+----------
public | pelanggan | table | postgres
(1 row)
Table "public.pelanggan"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+-----------------
id | integer | | not null |
nama | text | | not null |
email | text | | |
kota | text | | | 'Jakarta'::text
Indexes:
"pelanggan_pkey" PRIMARY KEY, btree (id)
"pelanggan_email_key" UNIQUE CONSTRAINT, btree (email)Mari kita baca hasilnya bagian demi bagian:
\dtmenghasilkan daftar relasi: schema (public), nama tabel (pelanggan), jenis objek (table), dan pemiliknya (postgres— pengguna yang menjalankanCREATE TABLE).\d pelangganmenghasilkan tabel kolom: nama kolom, tipe, collation (aturan urutan teks — kosong di sini), status NULL (not nullatau kosong), dan nilai default. Bariskotamemperlihatkan'Jakarta'::text— default yang kita definisikan, lengkap dengan cast ke tipetextyang ditambahkan server.- Bagian
Indexes:di bawahnya mendaftar index yang tercipta otomatis oleh constraint:pelanggan_pkeyuntuk primary key danpelanggan_email_keyuntukUNIQUE. Kedua index ini dibuat server tanpa kita minta.
Bentuk \d+ menambahkan kolom-kolom teknis — cara penyimpanan fisik tiap kolom (Storage), target statistik, dan deskripsi — yang mulai berguna saat kita menyelami performa nanti:
\d+ pelangganOutput yang Dihasilkan:
Table "public.pelanggan"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
--------+---------+-----------+----------+-----------------+----------+-------------+--------------+-------------
id | integer | | not null | | plain | | |
nama | text | | not null | | extended | | |
email | text | | | | extended | | |
kota | text | | | 'Jakarta'::text | extended | | |
Indexes:
"pelanggan_pkey" PRIMARY KEY, btree (id)
"pelanggan_email_key" UNIQUE CONSTRAINT, btree (email)
Access method: heapOutput \d+ memperlihatkan informasi tambahan seperti plain dan extended pada kolom Storage (strategi kompresi dan penyimpanan tiap tipe data) — detail yang kita abaikan dulu dan bahas kembali di Section Query Optimization. Yang penting sekarang: pola \d dan \d+ selalu siap sebagai jendela cepat ke struktur mana pun.
information_schema: Cara Standar SQL #
information_schema adalah kumpulan view yang didefinisikan standar SQL untuk memetakan struktur database. Karena bentuknya query SQL biasa, hasilnya bisa dibaca dari psql, dari aplikasi, bahkan (dengan nama view yang sama) dari database lain seperti MySQL — itulah nilai utamanya. View information_schema.columns memuat satu baris per kolom dari semua tabel:
SELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'pelanggan'
ORDER BY ordinal_position;Output yang Dihasilkan:
column_name | data_type | is_nullable | column_default
-------------+-----------+-------------+-----------------
id | integer | NO |
nama | text | NO |
email | text | YES |
kota | text | YES | 'Jakarta'::text
(4 rows)Empat hal penting dari query tersebut: saringan table_schema dan table_name mempersempit hasil ke tabel yang kita tuju; kolom ordinal_position adalah nomor urut kolom sesuai definisi — dan ORDER BY ordinal_position menjamin baris tampil persis dalam urutan itu (tanpa ORDER BY, urutan baris hasil query tidak dijamin); is_nullable bernilai NO atau YES; dan column_default menampilkan nilai default kota dalam bentuk aslinya. Nilai untuk primary key id terlihat beda dari \d: information_schema tidak punya kolom khusus “primary key” — informasi itu hidup di view information_schema.table_constraints yang kita kenal nanti.
pg_catalog: Sumber Aslinya #
Kedua pintu sebelumnya membaca dari satu sumber yang sama: system catalog — tabel-tabel internal bernama pg_* tempat PostgreSQL sungguhan menyimpan seluruh metadata-nya. Ketika psql menjalankan \d, psql menjalankan query ke catalog inilah di belakang layar. Satu contoh kecil memperlihatkan rasanya:
SELECT attname AS nama_kolom,
format_type(atttypid, atttypmod) AS tipe_kolom
FROM pg_attribute
WHERE attrelid = 'pelanggan'::regclass
AND attnum > 0
AND NOT attisdropped
ORDER BY attnum;Output yang Dihasilkan:
nama_kolom | tipe_kolom
------------+------------
id | integer
nama | text
email | text
kota | text
(4 rows)Catalog pg_attribute menyimpan satu baris per kolom per tabel, termasuk kolom sistem tersembunyi yang kita saring dengan attnum > 0. Nilai 'pelanggan'::regclass mengubah nama tabel menjadi penunjuk internal (OID — nomor objek internal server), dan function format_type() menerjemahkan kode tipe numerik menjadi nama tipe yang kita kenal seperti integer dan text. Catalog kaya informasi dan cepat, tetapi namanya khas PostgreSQL dan isinya bisa berubah antar versi besar — untuk kode yang perlu portabel, information_schema tetap pilihan lebih aman.
Mana yang Dipakai Kapan? #
Ketiga pintu tersebut saling melengkapi, bukan bersaing:
| Kebutuhan | Pilihan tepat | Alasan |
|---|---|---|
| Cek cepat sambil bekerja di terminal | \d, \dt, \d+ | Paling ringkas, tanpa menulis query |
| Kode aplikasi yang perlu memeriksa struktur | information_schema | SQL standar yang sama di banyak database |
| Informasi internal yang tidak ada di standar | pg_catalog | Satu-satunya sumber data lengkap |
Satu hal yang tidak berubah di ketiganya: struktur tabel yang terbaca adalah struktur yang sedang berlaku saat ini. Begitu kita mengubah definisi tabel, semua pembacaan berikutnya menampilkan bentuk barunya — dan mengubah struktur itulah topik chapter berikutnya, Mengubah Struktur Tabel.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
buat-tabel.sql
Unduh berkasCREATE TABLE pelanggan (
id integer PRIMARY KEY,
nama text NOT NULL,
email text UNIQUE,
kota text DEFAULT 'Jakarta'
);
INSERT INTO pelanggan (id, nama, email)
VALUES (1, 'Budi', '[email protected]');
deskripsi-tabel.sql
Unduh berkas\dt
\d pelanggan
detail-tabel.sql
Unduh berkas\d+ pelanggan
informasi-kolom.sql
Unduh berkasSELECT column_name, data_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = 'pelanggan'
ORDER BY ordinal_position;
katalog-sistem.sql
Unduh berkasSELECT attname AS nama_kolom,
format_type(atttypid, atttypmod) AS tipe_kolom
FROM pg_attribute
WHERE attrelid = 'pelanggan'::regclass
AND attnum > 0
AND NOT attisdropped
ORDER BY attnum;