TL;DR
VIEW adalah query SELECT yang disimpan dengan nama, dan bisa dipanggil kayak tabel biasa. Perintahnya CREATE VIEW nama_view AS SELECT .... VIEW gak nyimpen data, cuma nyimpen definisi query-nya, jadi hasilnya selalu segar tiap dipanggil. Kalau kamu butuh hasilnya disimpan biar cepat, pakai materialized view.
VIEW adalah query SELECT yang disimpan dengan nama, dan bisa dipanggil kayak tabel biasa. Perintahnya CREATE VIEW nama_view AS SELECT ....
Masalah yang dia selesain: kamu punya query 40 baris dengan 3 JOIN dan 5 filter. Query itu kamu pakai tiap minggu. Rekan kamu juga pakai, tapi versinya rada beda. Akhir bulan, angka kalian gak sama, dan gak ada yang tau siapa yang bener.
VIEW bikin definisi itu cuma ada satu. Semua orang narik dari sumber yang sama.
VIEW adalah objek database yang nyimpen definisi query, bukan datanya. Waktu kamu SELECT dari view, database ngejalanin query yang tersimpan di dalamnya lalu ngasih hasilnya.
Efeknya: data yang kamu lihat selalu segar. Tapi view gak bikin query jadi lebih cepat. Dia cuma bikin query jadi lebih rapi dan bisa dipakai ulang.
CREATE VIEW v_penjualan_bulanan AS
SELECT
DATE_TRUNC('month', t.tanggal) AS bulan,
t.kota,
p.kategori,
SUM(t.total) AS omzet,
COUNT(*) AS jumlah_transaksi
FROM transaksi t
JOIN produk p ON p.id = t.produk_id
WHERE t.status = 'selesai'
GROUP BY 1, 2, 3;
Sekarang query 12 baris itu punya nama. Panggilnya:
SELECT bulan, SUM(omzet) AS total_omzet
FROM v_penjualan_bulanan
WHERE kota = 'Bandung'
GROUP BY bulan
ORDER BY bulan;
Lima baris. Yang tadinya butuh kamu inget struktur 2 tabel plus aturan filter, sekarang tinggal panggil namanya.
Awalan v_ itu konvensi, bukan aturan. Tapi bikin orang lain langsung tau mana view mana tabel.
| Nyimpen data? | Hidup selamanya? | Bisa dipakai orang lain? | |
|---|---|---|---|
| Tabel | Ya | Ya | Ya |
| VIEW | Nggak, cuma definisi query | Ya | Ya |
| Materialized view | Ya, hasilnya disimpan | Ya | Ya |
| CTE (WITH) | Nggak | Nggak, mati begitu query selesai | Nggak |
Aturan gampangnya:
Ubah definisinya tanpa hapus dulu:
CREATE OR REPLACE VIEW v_penjualan_bulanan AS
SELECT ...;
Ada batasannya: kamu gak bisa ngilangin kolom atau ganti urutannya lewat REPLACE di sebagian besar database. Nambah kolom di belakang boleh. Kalau mau rombak total, DROP dulu.
DROP VIEW v_penjualan_bulanan;
Hati-hati kalau view kamu dipakai view lain atau dashboard. DROP bakal bikin semuanya rusak. Cek dulu siapa yang make.
VIEW biasa ngitung ulang tiap kali dipanggil. Kalau query di dalamnya berat, tiap panggilan berat.
Materialized view nyimpen hasilnya di disk. Panggilan berikutnya tinggal baca hasil jadi.
CREATE MATERIALIZED VIEW mv_penjualan_bulanan AS
SELECT ...;
Harganya: datanya gak segar sendiri. Kamu harus refresh manual atau lewat jadwal.
REFRESH MATERIALIZED VIEW mv_penjualan_bulanan;
Pakai materialized view kalau tiga hal ini kena semua: query-nya berat, hasilnya dipanggil sering, dan data telat beberapa jam masih oke. Laporan bulanan? Cocok. Saldo rekening? Jangan.
Detail perilaku refresh dan penguncian tabelnya ada di dokumentasi CREATE MATERIALIZED VIEW PostgreSQL.
Dataset ngulikdata toko_berkah punya 4.812 baris transaksi. Tapi gak semuanya sah dihitung sebagai penjualan.
Aturannya, setelah ngobrol sama pemilik toko:
selesai, buang yang batal dan pendingTEST)Tiga aturan. Kedengeran gampang. Sampai tiga orang di tim nulis versinya masing-masing dan lupa satu aturan.
Itu yang kejadian. Laporan Januari dari orang A: Rp284 juta. Dari orang B: Rp291 juta. Selisih Rp7 juta, dan dua-duanya yakin bener.
Perbaikannya satu view:
CREATE VIEW v_transaksi_valid AS
SELECT *
FROM transaksi
WHERE status = 'selesai'
AND total > 0
AND kode_pelanggan NOT LIKE 'TEST%';
Dari 4.812 baris, yang lolos 4.516. Yang kebuang 296 baris, sekitar 6% data.
Sekarang semua query di tim mulai dari v_transaksi_valid, bukan dari transaksi. Aturannya berubah bulan depan? Ubah view-nya sekali, semua laporan ikut.
Itu manfaat VIEW yang paling gede, dan sering gak kelihatan sampai kamu pernah ngalamin dua laporan yang angkanya beda.
Nggak. VIEW cuma nyimpen teks query. Kalau query aslinya butuh 8 detik, view-nya juga 8 detik.
Mau cepat? Pasang index di kolom yang dipakai di WHERE dan JOIN, atau pindah ke materialized view.
View A narik dari view B, yang narik dari view C. Empat level ke dalam, dan gak ada yang tau query aslinya kayak apa. Debug-nya mimpi buruk.
Patokan aku: maksimal 2 level. Lebih dari itu, tulis ulang.
-- rapuh
CREATE VIEW v_produk AS SELECT * FROM produk;
Kolom baru ditambahin ke tabel produk? Perilaku view-nya jadi gak konsisten antar database. Sebutin kolomnya satu-satu.
-- jangan
WHERE tanggal >= '2026-01-01'
Tahun depan view ini bohong. Biarin filter tanggal di query pemanggilnya, bukan di dalam view.
Kalau cuma dipakai sekali, itu CTE. View yang gak kepake cuma bikin database kamu penuh sampah yang gak ada yang berani hapus.
Empat situasi di mana view hampir selalu layak:
Pola yang aku pakai: satu view "bersih" per tabel penting, isinya aturan validasi. Semua analisis mulai dari situ.
VIEW adalah query SELECT yang disimpan dengan sebuah nama, dan bisa dipanggil kayak tabel biasa. Perintahnya CREATE VIEW nama_view AS SELECT dan seterusnya. Waktu kamu SELECT dari view itu, database ngejalanin query yang tersimpan di dalamnya, lalu ngasih hasilnya. Jadi view gak nyimpen data sendiri, dia cuma nyimpen definisi query-nya.
Tabel nyimpen data beneran di disk. VIEW cuma nyimpen teks query-nya, dan datanya diambil segar dari tabel asli tiap kali view dipanggil. Artinya view selalu nunjukin data terbaru, tapi dia gak bikin query jadi lebih cepat. Kalau tabel aslinya lambat, view yang mengambil darinya juga lambat.
CTE (WITH) cuma hidup selama satu query jalan. Habis itu hilang. Pakai CTE kalau kamu cuma butuh mecah satu query panjang biar kebaca. VIEW disimpan permanen di database dan bisa dipanggil siapa aja, kapan aja. Pakai VIEW kalau query yang sama dipakai berulang-ulang, apalagi kalau dipakai lebih dari satu orang.
Materialized view nyimpen hasil query-nya beneran di disk, bukan cuma definisinya. Jadi waktu dipanggil, dia gak ngitung ulang, langsung ngasih hasil yang udah jadi. Ini bikin query berat jadi jauh lebih cepat. Harganya: datanya gak otomatis segar, kamu harus jalanin REFRESH MATERIALIZED VIEW biar hasilnya update.
Bisa, tapi cuma untuk view sederhana yang narik dari satu tabel tanpa GROUP BY, DISTINCT, atau agregasi. Kalau view kamu punya JOIN atau SUM, database bakal nolak perintah tulisnya. Sebagian besar view yang dipakai analis memang cuma buat baca, jadi batasan ini jarang jadi masalah di kerjaan sehari-hari.
Cek query yang paling sering kamu copy-paste minggu ini. Kalau kamu nemu satu yang udah kamu tempel 3 kali, itu kandidat view pertama kamu.
Lanjut: referensi fungsi SELECT dan apa itu query optimization di glosarium ngulikdata.
Mau praktek langsung? Mulai latihan SQL gratis
Latihan interaktif, langsung di browser.
Analisa per kuartal, hari kerja, atau musim jadi ribet kalau tiap query ngitung ulang atribut tanggal. Tabel kalender nyimpen semua atribut itu sekali, biar tinggal di-JOIN.
Laporan penjualan harian sering bolong di hari tanpa transaksi. Ini cara bikin deret tanggal lengkap di SQL biar tiap hari muncul, walau nilainya nol.
Struktur organisasi tersimpan sebagai kolom id_atasan yang saling nunjuk. Ini cara narik rantai jabatan, hitung total bawahan, dan span of control cuma pakai SQL.