Constraint SQL: NOT NULL, UNIQUE, CHECK, DEFAULT
TL;DR
Constraint SQL adalah aturan yang dipasang di kolom atau tabel supaya database nolak data yang gak sesuai sebelum data itu kesimpan. Empat yang paling sering dipakai: NOT NULL bikin kolom gak boleh kosong, UNIQUE bikin nilainya gak boleh kembar, CHECK ngecek syarat logika kayak harga harus di atas nol, dan DEFAULT ngisi nilai otomatis kalau kolomnya dikosongin. Constraint dijaga sama database, jadi tetap jalan walau datanya masuk lewat aplikasi lain.
Constraint adalah aturan yang dipasang di kolom atau tabel supaya database nolak data yang gak sesuai. Data sampah ditahan di pintu masuk, bukan dibersihin tiga bulan kemudian.
Empat yang paling sering dipakai: NOT NULL, UNIQUE, CHECK, dan DEFAULT.
Bedanya sama validasi di aplikasi: constraint dijaga database. Data yang masuk lewat impor CSV, skrip Python, atau tim lain yang gak tau aturanmu — semuanya kena.
Apa itu constraint di SQL?
Constraint adalah aturan yang nempel di struktur tabel dan dicek otomatis tiap kali ada data masuk atau diubah. Kalau datanya melanggar, database nolak seluruh baris itu dan ngasih pesan error — gak ada yang setengah kesimpan.
Ini contoh tabel produk dengan empat constraint terpasang sekaligus:
CREATE TABLE produk (
id_produk INT PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
sku VARCHAR(30) UNIQUE NOT NULL,
kategori VARCHAR(50) NOT NULL DEFAULT 'Lainnya',
harga DECIMAL(12,2) NOT NULL CHECK (harga > 0),
stok INT NOT NULL DEFAULT 0 CHECK (stok >= 0)
);
Satu tabel, enam kolom, enam aturan. Sekarang bedah satu-satu.
Apa fungsi NOT NULL?
NOT NULL bikin kolom gak boleh kosong. Titik.
INSERT INTO produk (id_produk, nama, sku, harga) VALUES
(5, NULL, 'SNK-002', 9000.00);
-- ERROR: null value in column "nama" violates not-null constraint
Kelihatan sepele. Tapi kolom yang boleh kosong bikin masalah berantai di query.
Contohnya: kalau kolom harga boleh NULL, maka SUM(harga) diam-diam ngelewatin baris itu. Total penjualanmu kurang, dan gak ada satu pun error yang muncul.
Aturan praktis: kasih NOT NULL ke semua kolom yang secara bisnis wajib ada isinya. Kalau kamu ragu "boleh kosong gak ya?", jawabannya biasanya gak boleh.
Cara NULL bikin agregasi meleset dijelasin lebih lengkap di halaman glosarium NULL.
Apa fungsi UNIQUE?
UNIQUE bikin nilai di satu kolom gak boleh kembar.
INSERT INTO produk (id_produk, nama, sku, harga) VALUES
(6, 'Kopi Sachet Baru', 'MIN-001', 3000.00);
-- ERROR: duplicate key value violates unique constraint
SKU MIN-001 udah dipakai produk lain. Ditolak.
Bedanya sama PRIMARY KEY apa?
| Sifat | PRIMARY KEY | UNIQUE |
|---|---|---|
| Boleh kembar | Nggak | Nggak |
| Boleh kosong | Nggak | Boleh |
| Jumlah per tabel | Cuma 1 | Boleh banyak |
Jadi: id_produk jadi primary key, sementara sku dan email masing-masing bisa dikasih UNIQUE tanpa bentrok.
Perbandingan lengkapnya ada di artikel primary key dan foreign key.
Apa fungsi CHECK?
CHECK ngecek syarat logika. Kalau syaratnya gak kepenuhi, barisnya ditolak.
harga DECIMAL(12,2) NOT NULL CHECK (harga > 0)
Coba masukin produk dengan harga 0:
INSERT INTO produk (id_produk, nama, sku, harga) VALUES
(7, 'Sampel Gratis', 'SMP-001', 0.00);
-- ERROR: new row violates check constraint
Ditolak. Kalau kamu memang butuh nyimpen produk gratis, ganti aturannya jadi CHECK (harga >= 0) — tapi itu keputusan bisnis, bukan kelalaian.
CHECK buat batasin daftar nilai
Ini yang paling sering kepake:
status VARCHAR(20) NOT NULL DEFAULT 'aktif'
CHECK (status IN ('aktif', 'nonaktif', 'habis'))
Sekarang kolom status cuma bisa diisi tiga nilai itu. Ada yang nulis "Aktif" pakai huruf besar? Ditolak. "pending"? Ditolak.
Tanpa CHECK, kolom status di database nyata biasanya berakhir kayak gini: "aktif", "Aktif", "AKTIF", "active", "1", dan "". Lima variasi buat satu makna, dan setiap laporan yang ngelompokin status jadi salah.
CHECK yang ngebandingin dua kolom
CREATE TABLE promo (
id_promo INT PRIMARY KEY,
kode VARCHAR(20) UNIQUE NOT NULL,
mulai DATE NOT NULL,
selesai DATE NOT NULL,
CONSTRAINT ck_periode_promo CHECK (selesai >= mulai)
);
Promo yang selesai sebelum dimulai? Gak bisa masuk. Aturan ini ditaruh di level tabel karena nyentuh dua kolom sekaligus.
Apa fungsi DEFAULT?
DEFAULT ngisi nilai otomatis kalau kolomnya gak disebut waktu insert.
INSERT INTO produk (id_produk, nama, sku, harga) VALUES
(4, 'Gula Pasir 1kg', 'SMB-002', 16000.00);
-- kategori otomatis jadi 'Lainnya', stok jadi 0, status jadi 'aktif'
Yang paling sering dipakai: kolom timestamp.
dibuat_pada TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
Tiap baris baru otomatis dapat cap waktu. Gak perlu diisi manual, gak bisa lupa.
Jebakan DEFAULT yang paling sering bikin bingung
DEFAULT cuma jalan kalau kolomnya sama sekali gak disebut di INSERT.
-- kategori kena DEFAULT 'Lainnya'
INSERT INTO produk (id_produk, nama, sku, harga)
VALUES (10, 'Teh Celup', 'MIN-003', 8000);
-- kategori jadi NULL, DEFAULT gak jalan
INSERT INTO produk (id_produk, nama, sku, kategori, harga)
VALUES (11, 'Teh Tarik', 'MIN-004', NULL, 9000);
Yang kedua bakal ditolak, karena kolom kategori juga punya NOT NULL.
Ini yang bikin impor CSV sering gagal massal — sel kosong di CSV kekirim sebagai NULL eksplisit, bukan sebagai "gak disebut".
Contoh kasus: kolom status di toko_berkah
Waktu aku ngecek tabel produk di dataset toko_berkah — 1.847 baris, dikumpulin dari 3 sistem berbeda selama 2 tahun — kolom status gak punya CHECK constraint sama sekali.
Isinya:
| Nilai | Jumlah baris |
|---|---|
| aktif | 1.203 |
| Aktif | 287 |
| AKTIF | 94 |
| active | 41 |
| nonaktif | 178 |
| (kosong) | 44 |
Query WHERE status = 'aktif' ngeluarin 1.203 baris. Padahal produk aktif yang sebenernya ada 1.625 — selisih 422 baris, atau 26%.
Laporan ketersediaan produk yang dipakai tim purchasing selama setahun bilang stok aktifnya 1.203. Mereka pesan ulang berdasarkan angka itu.
Satu baris CHECK constraint waktu tabelnya pertama dibikin — dan 422 baris salah klasifikasi itu gak pernah ada.
Gimana cara nambahin constraint ke tabel yang udah ada?
Pakai ALTER TABLE:
ALTER TABLE produk
ADD CONSTRAINT ck_harga_wajar CHECK (harga <= 10000000);
Tapi ada satu langkah yang wajib duluan: cek data lama.
Database bakal nolak ALTER TABLE kalau ada satu aja baris lama yang melanggar aturannya. Dan pesan errornya jarang nunjukin baris mana yang bermasalah.
Cari dulu pakai SELECT:
SELECT id_produk, nama, harga
FROM produk
WHERE harga <= 0 OR harga IS NULL;
Bersihin baris yang keluar, baru pasang constraintnya. Urutannya jangan dibalik.
Kesalahan umum
1. Ngandelin validasi di aplikasi doang
Form aplikasi kamu emang nolak harga minus. Tapi impor CSV nggak. Skrip cron nggak. Tim lain yang akses database langsung juga nggak.
Constraint di database jadi lapisan terakhir yang gak bisa dilewatin siapa pun.
2. Nganggep DEFAULT nyelamatin sel kosong dari CSV
Udah dibahas di atas. Sel kosong di CSV biasanya kekirim sebagai NULL eksplisit, dan DEFAULT gak jalan buat itu.
3. Lupa kasih nama constraint
Kalau kamu nulis CHECK (harga > 0) tanpa CONSTRAINT nama_aturan, database bikin nama acak kayak produk_harga_check1.
Setahun kemudian waktu kamu mau hapus atau ubah aturannya, kamu harus nyari dulu namanya. Kasih nama yang jelas sejak awal.
4. Bikin CHECK yang kelewat ketat
CHECK (harga >= 1000) kedengeran masuk akal — sampai ada produk promo seharga 500. Sekarang tim ops gak bisa masukin produknya, dan kamu harus ALTER TABLE di jam sibuk.
Constraint buat nahan data yang pasti salah, bukan data yang jarang terjadi.
5. UNIQUE di kolom yang bisa berubah
Email dan nomor HP bisa berubah, dan bisa dipakai ulang. UNIQUE di situ kadang bikin masalah waktu pelanggan lama daftar ulang. Pikirin dulu skenario perubahannya.
FAQ
Apa itu constraint di SQL?
Constraint adalah aturan yang dipasang di kolom atau tabel supaya database nolak data yang gak sesuai sebelum data itu kesimpan. Bedanya sama validasi di aplikasi: constraint dijaga database, jadi tetap jalan walau datanya masuk lewat impor CSV atau skrip lain.
Apa bedanya UNIQUE dan PRIMARY KEY?
Dua-duanya bikin nilai gak boleh kembar. Bedanya: primary key gak boleh kosong dan cuma boleh ada satu per tabel. UNIQUE boleh kosong dan boleh dipasang di banyak kolom sekaligus. Contohnya id_produk jadi primary key, sementara kolom SKU dan email masing-masing bisa dikasih UNIQUE.
Kapan pakai CHECK constraint?
Pakai CHECK kalau kamu punya aturan logika yang harus selalu benar, misalnya harga harus di atas nol atau tanggal selesai gak boleh sebelum tanggal mulai. CHECK juga bisa batasin isi kolom ke daftar tertentu pakai IN — ini jauh lebih aman dari cuma ngandelin dropdown di aplikasi.
Apakah DEFAULT jalan kalau kolomnya diisi NULL?
Nggak. DEFAULT cuma jalan kalau kolomnya sama sekali gak disebut di INSERT. Kalau kamu tulis NULL secara eksplisit, database nyimpen NULL — atau nolak baris itu kalau kolomnya juga NOT NULL. Ini yang paling sering bikin impor CSV gagal massal.
Bisa nambahin constraint ke tabel yang udah ada isinya?
Bisa pakai ALTER TABLE ADD CONSTRAINT, tapi database bakal nolak kalau ada data lama yang melanggar aturannya. Cek dulu pakai SELECT, bersihin, baru pasang. Daftar lengkap jenis constraint bisa kamu baca di dokumentasi constraint PostgreSQL.
Penutup
Yang perlu kamu bawa pulang:
- NOT NULL ke semua kolom yang secara bisnis wajib ada isinya. Kalau ragu, biasanya jawabannya wajib.
- CHECK dengan IN ke tiap kolom status atau kategori. Ini yang nyelametin kamu dari lima variasi ejaan buat satu makna.
- Sebelum
ALTER TABLE ADD CONSTRAINT, cek data lama pakai SELECT dulu.
Coba jalanin query cek nilai unik di kolom status database kamu sekarang. Kalau keluar lebih dari yang kamu harapkan, kamu baru nemu sumber laporan yang selama ini meleset.
Mau ngerti relasi antar tabel dulu? Baca panduan primary key dan foreign key. Buat yang mau lancar nyaring data, ada panduan WHERE di SQL lengkap.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Artikel Terkait
7 SQL Client Gratis Terbaik buat Analis Data (2026)
Nggak perlu bayar buat nulis query. Ini 7 SQL client gratis yang beneran dipakai analis, plus kelebihan dan kekurangannya masing-masing.
SQL Style Guide: Cara Nulis Query yang Enak Dibaca Tim
Sepuluh aturan SQL style guide yang bikin query kamu kebaca sama tim — dan sama kamu sendiri 6 bulan lagi. Lengkap dengan contoh sebelum-sesudah.
Take-Home Test SQL Data Analyst: Contoh Soal + Cara Ngerjainnya
Contoh soal take-home test SQL yang beneran dipakai perusahaan, dikerjain step by step — dari baca soal, nulis query, sampai nyusun insight yang bikin recruiter nengok.