Hampir setiap tabel punya kolom yang nilainya hampir selalu sama: anggota baru langsung berstatus aktif, voucher diberi kode berurutan, saldo awal selalu Rp50.000. Memaksa aplikasi menyebut nilai-nilai itu di setiap INSERT membuat kode repetitif dan rawan salah tulis — satu variabel yang lupa diisi dan data pun menjadi tidak konsisten. Klausa DEFAULT memindahkan tanggung jawab itu ke definisi tabel: server yang mengisi nilai bawaan setiap kali kolomnya tidak diisi secara eksplisit. Pada chapter ini kita memasang default pada tabel keanggotaan, mengamati kapan nilainya dipakai dan kapan tidak, lalu menutup dengan pola default dinamis memakai sequence.
Memasang DEFAULT saat Membuat Tabel #
Nilai bawaan dideklarasikan sebagai bagian dari definisi kolom di CREATE TABLE — satu klausa DEFAULT diikuti nilai atau ekspresi. Tabel anggota berikut memakai empat bentuk sekaligus: konstanta teks, literal date, konstanta numerik, dan ekspresi aritmetika:
-- Tabel keanggotaan dengan nilai bawaan di kolom-kolom opsionalnya
CREATE TABLE anggota (
id integer PRIMARY KEY,
nama text NOT NULL,
kota text DEFAULT 'Jakarta',
bergabung date DEFAULT DATE '2026-01-01',
saldo numeric(12, 2) DEFAULT 50000.00,
iuran_tahunan numeric(12, 2) DEFAULT 2500.00 * 2
);
\d anggotaOutput yang Dihasilkan:
CREATE TABLE
Table "public.anggota"
Column | Type | Collation | Nullable | Default
---------------+---------------+-----------+----------+------------------------
id | integer | | not null |
nama | text | | not null |
kota | text | | | 'Jakarta'::text
bergabung | date | | | '2026-01-01'::date
saldo | numeric(12,2) | | | 50000.00
iuran_tahunan | numeric(12,2) | | | (2500.00 * 2::numeric)
Indexes:
"anggota_pkey" PRIMARY KEY, btree (id)Kolom Default pada hasil \d memperlihatkan bagaimana server menyimpan aturan itu. Teks dan tanggal ditampilkan sebagai literal bertipe ('Jakarta'::text, '2026-01-01'::date), angka tampil apa adanya (50000.00), dan ekspresi 2500.00 * 2 disimpan sebagai ekspresi — (2500.00 * 2::numeric) — lalu dihitung setiap kali nilai bawaannya dibutuhkan. Perhatikan juga dua hal yang sering disalahpahami: DEFAULT bukan bagian dari tipe data, melainkan aturan terpisah; dan id tidak punya default apa pun, sehingga wajib diisi di setiap INSERT.
Kapan Nilai Bawaan Dipakai #
Nilai bawaan bekerja pada dua situasi saja: ketika kolom tidak disebutkan dalam daftar kolom INSERT, dan ketika nilainya ditulis sebagai kata kunci DEFAULT. Nilai eksplisit apa pun yang kita tulis sendiri selalu menang:
-- Kolom yang tidak disebutkan menerima nilai bawaannya
INSERT INTO anggota (id, nama) VALUES (1, 'Budi');
-- Kata kunci DEFAULT memakai nilai bawaan secara eksplisit
INSERT INTO anggota (id, nama, kota) VALUES (2, 'Siti', DEFAULT);
-- Nilai yang disebut sendiri selalu menang atas nilai bawaan
INSERT INTO anggota (id, nama, kota, saldo) VALUES (3, 'Andi', 'Bandung', 120000.00);
SELECT id, nama, kota, bergabung, saldo, iuran_tahunan
FROM anggota
ORDER BY id;Output yang Dihasilkan:
INSERT 0 1
INSERT 0 1
INSERT 0 1
id | nama | kota | bergabung | saldo | iuran_tahunan
----+------+---------+------------+-----------+---------------
1 | Budi | Jakarta | 2026-01-01 | 50000.00 | 5000.00
2 | Siti | Jakarta | 2026-01-01 | 50000.00 | 5000.00
3 | Andi | Bandung | 2026-01-01 | 120000.00 | 5000.00
(3 rows)Mari kita bedah hasilnya baris demi baris:
- Baris Budi hanya mengisi
iddannama— empat kolom sisanya diisi server:kotamenjadiJakarta,bergabungmenjadi2026-01-01,saldomenjadi50000.00, daniuran_tahunanmenjadi5000.00(hasil evaluasi2500.00 * 2). - Baris Siti menyebut
kotasecara eksplisit tetapi nilainya kata kunciDEFAULT, bukan teks — hasilnya sama saja dengan tidak menyebut kolomnya. Bentuk ini berguna saat aplikasi ingin menyatakan niat secara gamblang atau saat menimpa default lewat parameter yang bisa NULL. - Baris Andi membuktikan urutan prioritas:
kotadiisi'Bandung'dansaldodiisi120000.00, sementara kolom yang tidak disebut tetap memakai bawaannya.
Jebakan: NULL Bukan Nilai Bawaan #
Menulis NULL secara eksplisit berarti “saya tahu kolom ini ada, dan nilainya tidak diketahui” — itu adalah nilai yang kita berikan, bukan kolom yang terlewat. Karena itu NULL tidak digantikan oleh DEFAULT:
-- NULL eksplisit TIDAK digantikan nilai bawaan
INSERT INTO anggota (id, nama, kota) VALUES (4, 'Tono', NULL);
SELECT id, nama, kota
FROM anggota
WHERE id = 4;Output yang Dihasilkan:
INSERT 0 1
id | nama | kota
----+------+------
4 | Tono |
(1 row)Baris Tono tersimpan dengan kota NULL meskipun default kolomnya adalah 'Jakarta'. Perilaku ini mengikuti standar SQL: server memakai DEFAULT hanya saat tidak ada nilai sama sekali, sedangkan NULL adalah nilai yang sah dan disengaja. Implikasinya nyata pada aplikasi yang memetakan form HTML ke INSERT — field kosong yang dikirim sebagai NULL akan menembus default, dan solusinya adalah memakai kata kunci DEFAULT (atau menghapus kolom itu dari daftar) saat inputnya kosong.
Mengubah dan Melepas Default #
Tabel yang sudah berjalan tetap bisa diatur ulang tanpa membangun ulang: ALTER COLUMN ... SET DEFAULT memasang aturan baru dan DROP DEFAULT melepasnya. Keduanya hanya mengatur baris-baris baru — data lama tidak tersentuh dan tidak ditulis ulang:
-- SET DEFAULT mengganti aturan; hanya baris baru yang terpengaruh
ALTER TABLE anggota ALTER COLUMN kota SET DEFAULT 'Bandung';
INSERT INTO anggota (id, nama) VALUES (5, 'Dewi');
-- DROP DEFAULT melepas aturan; kolom kembali tanpa nilai bawaan
ALTER TABLE anggota ALTER COLUMN kota DROP DEFAULT;
INSERT INTO anggota (id, nama) VALUES (6, 'Rina');
SELECT id, nama, kota
FROM anggota
WHERE id >= 4
ORDER BY id;Output yang Dihasilkan:
ALTER TABLE
INSERT 0 1
ALTER TABLE
INSERT 0 1
id | nama | kota
----+------+---------
4 | Tono |
5 | Dewi | Bandung
6 | Rina |
(3 rows)Tiga baris terakhir menceritakan keseluruhan siklusnya. Baris Tono (id 4) memuat NULL dari contoh sebelumnya. Dewi (id 5) disisipkan saat default kota masih 'Bandung', jadi Dewi mendapat 'Bandung'. Rina (id 6) disisipkan setelah DROP DEFAULT, sehingga kolom kota kembali kosong — NULL, seperti baris Tono. Baris Budi dan Siti yang lama tetap 'Jakarta' karena keduanya sudah tersimpan sebelum aturan diganti.
Default Dinamis dengan Sequence #
Semua default sejauh ini bernilai sama untuk setiap baris. Bentuk yang jauh lebih kuat adalah default yang maju setiap kali dipakai: sebuah sequence menghitung angka berurutan, dan fungsi nextval() mengambil angka berikutnya sekaligus menggeser hitungan sequence itu maju. Pola ini adalah cara klasik menghasilkan kode unik otomatis:
-- Pola klasik: sequence + nextval sebagai nilai bawaan dinamis
CREATE SEQUENCE seq_kode_voucher START 5000;
CREATE TABLE voucher (
kode integer PRIMARY KEY DEFAULT nextval('seq_kode_voucher'),
nama text NOT NULL
);
INSERT INTO voucher (nama) VALUES ('Diskon Lebaran');
INSERT INTO voucher (nama) VALUES ('Gratis Ongkir');
SELECT kode, nama
FROM voucher
ORDER BY kode;Output yang Dihasilkan:
CREATE SEQUENCE
CREATE TABLE
INSERT 0 1
INSERT 0 1
kode | nama
------+----------------
5000 | Diskon Lebaran
5001 | Gratis Ongkir
(2 rows)Dua INSERT sama sekali tidak menyebut kolom kode, dan hasilnya tetap unik: 5000 lalu 5001, sesuai START 5000 pada definisi sequence. Berbeda dari default konstanta, nilai ini tidak pernah berulang — setiap pemanggilan nextval() mengembalikan angka baru. Memasang pola ini secara manual (sequence terpisah, DEFAULT nextval(...), plus PRIMARY KEY) bekerja, tetapi PostgreSQL menyediakan sintaks yang lebih rapat dan terstandar untuk kebutuhan yang sama: identity column, yang menjadi fokus chapter berikutnya.
Default value mengisi kolom sekali, yaitu saat baris baru dibuat. Bagaimana jika kita ingin kolom yang nilainya selalu diturunkan dari kolom lain — misalnya nama lengkap yang otomatis tergabung dari nama depan dan belakang, dan ikut berubah setiap kali salah satu bagiannya diubah? Untuk itu PostgreSQL menyediakan generated column.
Referensi #
Berkas Sumber
Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.
buat-tabel.sql
Unduh berkas-- Tabel keanggotaan dengan nilai bawaan di kolom-kolom opsionalnya
CREATE TABLE anggota (
id integer PRIMARY KEY,
nama text NOT NULL,
kota text DEFAULT 'Jakarta',
bergabung date DEFAULT DATE '2026-01-01',
saldo numeric(12, 2) DEFAULT 50000.00,
iuran_tahunan numeric(12, 2) DEFAULT 2500.00 * 2
);
\d anggota
default-sekuens.sql
Unduh berkas-- Pola klasik: sequence + nextval sebagai nilai bawaan dinamis
CREATE SEQUENCE seq_kode_voucher START 5000;
CREATE TABLE voucher (
kode integer PRIMARY KEY DEFAULT nextval('seq_kode_voucher'),
nama text NOT NULL
);
INSERT INTO voucher (nama) VALUES ('Diskon Lebaran');
INSERT INTO voucher (nama) VALUES ('Gratis Ongkir');
SELECT kode, nama
FROM voucher
ORDER BY kode;
insert-default.sql
Unduh berkas-- Kolom yang tidak disebutkan menerima nilai bawaannya
INSERT INTO anggota (id, nama) VALUES (1, 'Budi');
-- Kata kunci DEFAULT memakai nilai bawaan secara eksplisit
INSERT INTO anggota (id, nama, kota) VALUES (2, 'Siti', DEFAULT);
-- Nilai yang disebut sendiri selalu menang atas nilai bawaan
INSERT INTO anggota (id, nama, kota, saldo) VALUES (3, 'Andi', 'Bandung', 120000.00);
SELECT id, nama, kota, bergabung, saldo, iuran_tahunan
FROM anggota
ORDER BY id;
null-bukan-default.sql
Unduh berkas-- NULL eksplisit TIDAK digantikan nilai bawaan
INSERT INTO anggota (id, nama, kota) VALUES (4, 'Tono', NULL);
SELECT id, nama, kota
FROM anggota
WHERE id = 4;
ubah-default.sql
Unduh berkas-- SET DEFAULT mengganti aturan; hanya baris baru yang terpengaruh
ALTER TABLE anggota ALTER COLUMN kota SET DEFAULT 'Bandung';
INSERT INTO anggota (id, nama) VALUES (5, 'Dewi');
-- DROP DEFAULT melepas aturan; kolom kembali tanpa nilai bawaan
ALTER TABLE anggota ALTER COLUMN kota DROP DEFAULT;
INSERT INTO anggota (id, nama) VALUES (6, 'Rina');
SELECT id, nama, kota
FROM anggota
WHERE id >= 4
ORDER BY id;