Chapter sebelumnya menunjukkan bahwa pg_catalog menyimpan seluruh metadata PostgreSQL — tetapi query ke katalog itu tidak akan jalan di MySQL, SQL Server, atau Oracle: nama kolom dan strukturnya khas PostgreSQL. Standard SQL menyiapkan jalan keluar: information_schema, kumpulan view berbasis standar yang isi dan namanya dijaga sama lintas database. Bagi tim yang menulis tool internal, skrip migrasi, atau laporan audit yang harus hidup di lebih dari satu mesin database, schema inilah antarmuka metadata paling aman. Chapter ini mengelilingi view-view terpentingnya dengan query yang berjalan di schema contoh kita, lalu menimbang kapan information_schema lebih baik dipakai daripada pg_catalog — dan kapan tidak.
Antarmuka Metadata Standar SQL #
information_schema adalah schema otomatis yang hadir di setiap database, berisi view — bukan table — di atas catalog internal. Konsekuensinya dua arah: isinya selalu segar tanpa perawatan, tetapi hanya memuat apa yang bisa dinyatakan dalam standar SQL. Nama-nama view pentingnya:
| View | Isi |
|---|---|
tables | Semua tabel dan view, dengan table_type pembeda |
columns | Semua kolom: tipe, panjang, nullable, posisi |
views | Daftar view plus flag is_updatable |
table_constraints | Semua constraint: PRIMARY KEY, UNIQUE, FOREIGN KEY, CHECK |
key_column_usage | Kolom yang menjadi bagian PK/UNIQUE/FK |
referential_constraints | Detail foreign key: rujukan dan aturan update/delete |
routines | Function dan procedure |
role_table_grants | Hak akses tabel per role |
Semua view ini menyaring berdasarkan table_schema/constraint_schema — tanpa filter, hasilnya bercampur baris-baris schema sistem.
tables dan columns #
File pertama menyiapkan schema contoh — dua tabel yang saling terhubung, satu view, satu function — dan file kedua membacanya dari dua view paling sering dipakai:
-- Skema contoh untuk dilihat dari information_schema
CREATE TABLE pelanggan (
id serial PRIMARY KEY,
nama varchar(50) NOT NULL,
email varchar(100) UNIQUE
);
CREATE TABLE pesanan (
id serial PRIMARY KEY,
pelanggan_id integer NOT NULL REFERENCES pelanggan(id),
total numeric(12,2) CHECK (total >= 0)
);
CREATE VIEW pesanan_ringkas AS
SELECT id, pelanggan_id, total FROM pesanan;
CREATE FUNCTION hitung_diskon(total numeric)
RETURNS numeric
LANGUAGE sql
IMMUTABLE
RETURN round(total * 0.1, 2);
INSERT INTO pelanggan (nama, email) VALUES
('Budi', '[email protected]'),
('Siti', '[email protected]');
INSERT INTO pesanan (pelanggan_id, total) VALUES
(1, 150000.00),
(2, 99000.00);Output yang Dihasilkan:
CREATE TABLE
CREATE TABLE
CREATE VIEW
CREATE FUNCTION
INSERT 0 2
INSERT 0 2-- Daftar tabel dan view menurut standar SQL
SELECT table_name, table_type
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;
-- Definisi kolom tabel pelanggan
SELECT column_name, data_type, character_maximum_length, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'pelanggan'
ORDER BY ordinal_position;Output yang Dihasilkan:
table_name | table_type
-----------------+------------
pelanggan | BASE TABLE
pesanan | BASE TABLE
pesanan_ringkas | VIEW
(3 rows)
column_name | data_type | character_maximum_length | is_nullable
-------------+-------------------+--------------------------+-------------
id | integer | | NO
nama | character varying | 50 | NO
email | character varying | 100 | YES
(3 rows)Dua hasil di atas memperlihatkan ciri khas information_schema. Pertama, nama tipe ditulis dalam istilah standar — character varying, bukan varchar — dan panjangnya terpisah di kolom sendiri, sehingga tool bisa memformatnya kembali ke dialek SQL mana pun. Kedua, jawaban atas “apa saja objek di schema ini?” dan “kolomnya apa saja?” tidak memerlukan join oid seperti di pg_catalog; cukup filter table_schema dan ORDER BY yang menentukan urutan penuh hasilnya.
Constraint Lintas View #
Informasi constraint terpecah ke beberapa view yang dirancang untuk di-join — pola persis seperti ERD kecil di dalam schema metadata:
-- Constraint beserta kolom yang menjadi kuncinya
SELECT tc.table_name, tc.constraint_type, tc.constraint_name, kcu.column_name
FROM information_schema.table_constraints tc
LEFT JOIN information_schema.key_column_usage kcu
ON kcu.constraint_schema = tc.constraint_schema
AND kcu.constraint_name = tc.constraint_name
WHERE tc.table_schema = 'public'
AND tc.constraint_name NOT LIKE '%not_null'
ORDER BY tc.table_name, tc.constraint_name, kcu.column_name NULLS FIRST;
-- Aturan foreign key berpasangan dengan unique constraint tujuannya
SELECT constraint_name, unique_constraint_name, update_rule, delete_rule
FROM information_schema.referential_constraints
WHERE constraint_schema = 'public'
ORDER BY constraint_name;Output yang Dihasilkan:
table_name | constraint_type | constraint_name | column_name
------------+-----------------+---------------------------+--------------
pelanggan | UNIQUE | pelanggan_email_key | email
pelanggan | PRIMARY KEY | pelanggan_pkey | id
pesanan | FOREIGN KEY | pesanan_pelanggan_id_fkey | pelanggan_id
pesanan | PRIMARY KEY | pesanan_pkey | id
pesanan | CHECK | pesanan_total_check |
(5 rows)
constraint_name | unique_constraint_name | update_rule | delete_rule
---------------------------+------------------------+-------------+-------------
pesanan_pelanggan_id_fkey | pelanggan_pkey | NO ACTION | NO ACTION
(1 row)Query pertama memakai LEFT JOIN karena constraint CHECK tidak punya kolom kunci — kolom column_name-nya kosong, seperti baris pesanan_total_check di hasil. Query kedua menunjukkan hal yang tidak dimiliki pg_constraint dalam bentuk langsung: relasi pesanan_pelanggan_id_fkey menunjuk pelanggan_pkey sebagai constraint tujuan, dengan aturan NO ACTION untuk UPDATE dan DELETE — bawaan yang setara ON UPDATE NO ACTION ON DELETE NO ACTION.
Grant, Routine, dan View #
Tiga view sisanya menjawab pertanyaan operasional sehari-hari — siapa boleh apa, function apa saja yang terpasang, dan view mana yang bisa ditulis:
-- Hak akses tabel untuk role yang sedang berjalan
SELECT table_name, privilege_type
FROM information_schema.role_table_grants
WHERE table_schema = 'public'
AND grantee = current_user
ORDER BY table_name, privilege_type;
-- Daftar function di schema kita
SELECT routine_name, routine_type, data_type
FROM information_schema.routines
WHERE routine_schema = 'public'
ORDER BY routine_name;
-- View dan status kebaruan datanya
SELECT table_name, is_updatable
FROM information_schema.views
WHERE table_schema = 'public'
ORDER BY table_name;Output yang Dihasilkan:
table_name | privilege_type
-----------------+----------------
pelanggan | DELETE
pelanggan | INSERT
pelanggan | REFERENCES
pelanggan | SELECT
pelanggan | TRIGGER
pelanggan | TRUNCATE
pelanggan | UPDATE
pesanan | DELETE
pesanan | INSERT
pesanan | REFERENCES
pesanan | SELECT
pesanan | TRIGGER
pesanan | TRUNCATE
pesanan | UPDATE
pesanan_ringkas | DELETE
pesanan_ringkas | INSERT
pesanan_ringkas | REFERENCES
pesanan_ringkas | SELECT
pesanan_ringkas | TRIGGER
pesanan_ringkas | TRUNCATE
pesanan_ringkas | UPDATE
(21 rows)
routine_name | routine_type | data_type
---------------+--------------+-----------
hitung_diskon | FUNCTION | numeric
(1 row)
table_name | is_updatable
-----------------+--------------
pesanan_ringkas | YES
(1 row)Tiga belas jenis hak pada dua tabel plus view itu berasal dari status kita sebagai pemilik objek — pemilik otomatis menerima seluruh privilege. View routines menampilkan hitung_diskon sebagai FUNCTION yang mengembalikan numeric, sementara views memberi tahu bahwa pesanan_ringkas adalah simple view yang is_updatable — PostgreSQL mengizinkan INSERT/UPDATE langsung ke view semacam itu tanpa trigger tambahan.
information_schema atau pg_catalog #
| Aspek | information_schema | pg_catalog |
|---|---|---|
| Status | Standar SQL, tersedia lintas database | Khas PostgreSQL |
| Portabilitas query | Tinggi — jalan di MySQL, SQL Server, dll | Nol — ganti database berarti ganti query |
| Cakupan objek | Yang bisa dinyatakan standar: tabel, kolom, constraint, grant | Semua: index, sequence, toast, extension, publication, dll |
| Detail teknis | Tidak ada — tanpa oid, tanpa relpages, tanpa storage | Lengkap — oid, relkind, relpages, reloptions, am |
| Stabilitas nama | Dijaga standard antar versi | Bisa berubah antar major version |
| Kebutuhan join | Ringkas — sedikit kolom kunci teks | Sering lewat oid antar katalog |
Aturan praktisnya sederhana. Untuk tool yang harus portabel — laporan skema, generator kode, skrip migrasi awal — pilih information_schema dan bersabar dengan cakupannya yang terbatas. Untuk pekerjaan administrasi PostgreSQL yang butuh detail teknis — ukuran relasi, definisi index, statistik planner — pg_catalog adalah satu-satunya sumber lengkap, dan itu sudah kita kuasai di chapter sebelumnya. Keduanya tidak saling menggantikan; keduanya membaca sumber kebenaran yang sama dari dua sudut yang berbeda.
Ada satu sumber kebenaran lagi yang selama ini hanya kita intip sepintas: log server — saksi bisu setiap query lambat, error, dan restart. Chapter Server Log membuka lembaran itu.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
constraint.sql
Unduh berkas-- Constraint beserta kolom yang menjadi kuncinya
SELECT tc.table_name, tc.constraint_type, tc.constraint_name, kcu.column_name
FROM information_schema.table_constraints tc
LEFT JOIN information_schema.key_column_usage kcu
ON kcu.constraint_schema = tc.constraint_schema
AND kcu.constraint_name = tc.constraint_name
WHERE tc.table_schema = 'public'
AND tc.constraint_name NOT LIKE '%not_null'
ORDER BY tc.table_name, tc.constraint_name, kcu.column_name NULLS FIRST;
-- Aturan foreign key berpasangan dengan unique constraint tujuannya
SELECT constraint_name, unique_constraint_name, update_rule, delete_rule
FROM information_schema.referential_constraints
WHERE constraint_schema = 'public'
ORDER BY constraint_name;
hak-dan-routine.sql
Unduh berkas-- Hak akses tabel untuk role yang sedang berjalan
SELECT table_name, privilege_type
FROM information_schema.role_table_grants
WHERE table_schema = 'public'
AND grantee = current_user
ORDER BY table_name, privilege_type;
-- Daftar function di schema kita
SELECT routine_name, routine_type, data_type
FROM information_schema.routines
WHERE routine_schema = 'public'
ORDER BY routine_name;
-- View dan status kebaruan datanya
SELECT table_name, is_updatable
FROM information_schema.views
WHERE table_schema = 'public'
ORDER BY table_name;
siapkan-skema.sql
Unduh berkas-- Skema contoh untuk dilihat dari information_schema
CREATE TABLE pelanggan (
id serial PRIMARY KEY,
nama varchar(50) NOT NULL,
email varchar(100) UNIQUE
);
CREATE TABLE pesanan (
id serial PRIMARY KEY,
pelanggan_id integer NOT NULL REFERENCES pelanggan(id),
total numeric(12,2) CHECK (total >= 0)
);
CREATE VIEW pesanan_ringkas AS
SELECT id, pelanggan_id, total FROM pesanan;
CREATE FUNCTION hitung_diskon(total numeric)
RETURNS numeric
LANGUAGE sql
IMMUTABLE
RETURN round(total * 0.1, 2);
INSERT INTO pelanggan (nama, email) VALUES
('Budi', '[email protected]'),
('Siti', '[email protected]');
INSERT INTO pesanan (pelanggan_id, total) VALUES
(1, 150000.00),
(2, 99000.00);
tabel-kolom.sql
Unduh berkas-- Daftar tabel dan view menurut standar SQL
SELECT table_name, table_type
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name;
-- Definisi kolom tabel pelanggan
SELECT column_name, data_type, character_maximum_length, is_nullable
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'pelanggan'
ORDER BY ordinal_position;