Cara Membuat View di MySQL

| | | MySQL (My Structured Query Language)
Cara Membuat View di MySQL

view itu tabel virtual yang dihasilkan dari query select. view tidak nyimpen data fisik, data diambil dari tabel asli tiap kali view diakses. view ini sangat berkaitan dengan fungsi agregat count, sum, dan avg karena sering dipakai buat nyederhanain laporan yang melibatkan kalkulasi.

saya mulai serius pakai view waktu query laporan di aplikasi sudah terlalu panjang buat dibaca, lebih dari 10 baris join yang harus ditulis ulang di tiga tempat berbeda. setelah dipindahin ke view, kode aplikasi menyusut drastis dan siapa pun di tim bisa pakai query yang sama tanpa takut salah ketik.

1. Kenapa Pakai View?

  • Sederhanain query kompleks, simpan query join yang rumit sebagai view
  • Keamanan, kasih akses ke view tanpa perlu akses ke tabel asli
  • Konsistensi, semua orang pakai query yang sama persis
  • Abstraksi, struktur tabel bisa berubah tanpa ngubah query user

contoh keamanan paling umum: tabel users punya kolom password dan email. daripada ngasih akses tabel itu ke tim laporan, buat view yang cuma menampilkan nama dan jumlah_transaksi. tim laporan dapat datanya, kolom sensitif tetap aman.

2. Membuat View

sintaks dasarnya CREATE VIEW nama_view AS <query>, lengkapnya ada opsi MySQL:

CREATE
  [OR REPLACE]
  [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
  [DEFINER = user] [SQL SECURITY { DEFINER | INVOKER }]
  VIEW nama_view AS <select_statement>
  [WITH [CASCADED | LOCAL] CHECK OPTION]

contoh paling simpel:

CREATE VIEW laporan_penjualan AS
SELECT 
    p.id,
    p.tanggal,
    c.nama as customer,
    pr.nama as produk,
    d.jumlah,
    d.harga,
    d.jumlah * d.harga as total
FROM penjualan p
JOIN customer c ON p.customer_id = c.id
JOIN penjualan_detail d ON p.id = d.penjualan_id
JOIN produk pr ON d.produk_id = pr.id;

sekali jalan, query join 4 tabel di atas jadi tersimpan dengan nama laporan_penjualan. kalau tidak tulis ALGORITHM, defaultnya UNDEFINED, MySQL akan pilih MERGE kalau bisa karena lebih cepat dan bisa pakai index, kalau tidak bisa baru pakai TEMPTABLE (hasil view dimasukin ke temporary table dulu).

3. Menggunakan View

pemakaiannya sama persis kayak tabel biasa:

SELECT * FROM laporan_penjualan;

SELECT customer, SUM(total) as total_belanja
FROM laporan_penjualan
GROUP BY customer;

yang menarik, data di view selalu fresh. begitu ada penjualan baru di tabel asli, hasil view langsung ikut berubah, tidak perlu refresh apa pun.

4. View dengan Kondisi

view juga bisa menyaring data dari awal:

CREATE VIEW produk_aktif AS
SELECT * FROM produk WHERE aktif = 1;

CREATE VIEW penjualan_bulan_ini AS
SELECT * FROM penjualan
WHERE MONTH(tanggal) = MONTH(CURDATE())
AND YEAR(tanggal) = YEAR(CURDATE());

dengan begini, tim marketing cukup SELECT * FROM produk_aktif, dijamin tidak akan pernah lihat produk yang sudah di-nonaktifkan.

5. Updatable View

ternyata view tidak cuma buat baca, view sederhana juga bisa di-insert, update, dan delete, dan perubahannya diteruskan ke tabel asli:

-- insert lewat view
INSERT INTO produk_aktif (nama, harga, aktif)
VALUES ('Mouse Wireless', 150000, 1);

-- update lewat view
UPDATE produk_aktif SET harga = 145000 WHERE nama = 'Mouse Wireless';

-- delete lewat view
DELETE FROM produk_aktif WHERE nama = 'Mouse Wireless';

syaratnya view harus updatable, artinya ada relasi satu-satu antara baris view dan baris tabel asli. praktisnya, hindari GROUP BY, DISTINCT, HAVING, UNION, LIMIT, fungsi agregat (SUM, COUNT), subquery di select list, atau join yang bikin baris jadi ambigu. kalau view cuma SELECT * FROM satu_tabel WHERE kondisi dan kolomnya map langsung ke kolom tabel, biasanya aman. view yang pakai TEMPTABLE juga otomatis tidak updatable.

6. WITH CHECK OPTION

ada jebakan menarik waktu update lewat view ber-filter. tanpa check option, data yang melanggar kondisi tetap bisa masuk tapi langsung tidak kelihatan:

-- tanpa check option
CREATE VIEW produk_aktif AS
SELECT * FROM produk WHERE aktif = 1;

-- ini jalan! tapi barisnya tidak kelihatan di view
UPDATE produk_aktif SET aktif = 0 WHERE id = 5;

baris id 5 jadi “hilang” dari view, padahal masuk. biar dicegah, tambahkan WITH CHECK OPTION:

CREATE OR REPLACE VIEW produk_aktif AS
SELECT * FROM produk WHERE aktif = 1
WITH CHECK OPTION;

-- sekarang error: CHECK OPTION failed
UPDATE produk_aktif SET aktif = 0 WHERE id = 5;

rule sederhananya, kalau view bakal dipakai buat nulis data, selalu pasang WITH CHECK OPTION. defaultnya CASCADED, artinya cek juga ke view induk di bawahnya. LOCAL cuma cek view itu sendiri plus view yang punya CHECK OPTION. cek statusnya lewat:

SELECT TABLE_NAME, CHECK_OPTION FROM INFORMATION_SCHEMA.VIEWS
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'produk_aktif';
-- nilai: NONE, CASCADED, atau LOCAL

7. Update dan Hapus View

cara ubah view pakai CREATE OR REPLACE VIEW, di MySQL ALTER VIEW juga ada dan fungsinya sama (alias). buat hapus pakai DROP VIEW:

-- Update view (ganti definisi)
CREATE OR REPLACE VIEW laporan_penjualan AS
SELECT p.id, p.tanggal, c.nama as customer,
        SUM(d.jumlah * d.harga) as total
FROM penjualan p
JOIN customer c ON p.customer_id = c.id
JOIN penjualan_detail d ON p.id = d.penjualan_id
GROUP BY p.id, p.tanggal, c.nama;

-- alternatif pakai ALTER (sama saja)
ALTER VIEW laporan_penjualan AS
SELECT p.id, p.tanggal, c.nama as customer,
        SUM(d.jumlah * d.harga) as total
FROM penjualan p
JOIN customer c ON p.customer_id = c.id
JOIN penjualan_detail d ON p.id = d.penjualan_id
GROUP BY p.id, p.tanggal, c.nama;

-- Lihat definisi view
SHOW CREATE VIEW laporan_penjualan;

-- Hapus view
DROP VIEW IF EXISTS laporan_penjualan;

8. View dan Performa

perlu diingat, view itu cuma query tersimpan, bukan hasil tersimpan. jadi:

  • kalau pakai MERGE, kondisi WHERE di luar view digabung ke dalam view pakai AND, jadi SELECT * FROM view_besar WHERE tanggal = '2026-08-01' bisa tetap pakai index tabel asli. cek pakai EXPLAIN, kalau kelihatan tabel asli langsung berarti MERGE jalan.
  • kalau pakai TEMPTABLE (terjadi kalau ada DISTINCT, GROUP BY, LIMIT, UNION, agregat), MySQL harus masukin semua baris view ke temporary table dulu baru di-filter, ini yang bikin lambat dan tidak bisa pakai index. TEMPTABLE juga bikin view tidak updatable.
  • view di atas view (nested view) bikin query makin berlapis, hindari kalau bisa
  • kalau butuh hasil yang benar-benar tersimpan fisik, mysql tidak punya materialized view, emulasinya pakai tabel biasa yang di-refresh lewat event scheduler atau trigger

buat view yang ringan, dan jangan ragu cek EXPLAIN kalau ada query yang tiba-tiba lambat setelah diubah ke view. kalau EXPLAIN muncul <derived> atau temptable, berarti sedang tidak MERGE.

9. Studi Kasus: Laporan Penjualan Bulanan

kombinasi view plus agregat buat laporan bulanan yang siap pakai:

-- view laporan ringkas
CREATE VIEW laporan_penjualan_bulanan AS
SELECT 
    DATE_FORMAT(p.tanggal, '%Y-%m') as bulan,
    c.nama as customer,
    COUNT(d.id) as jumlah_transaksi,
    SUM(d.jumlah * d.harga) as total_belanja
FROM penjualan p
JOIN customer c ON p.customer_id = c.id
JOIN penjualan_detail d ON p.id = d.penjualan_id
GROUP BY bulan, c.nama;

-- tinggal panggil
SELECT * FROM laporan_penjualan_bulanan
WHERE bulan = '2026-08'
ORDER BY total_belanja DESC;

sekali bikin, query laporan bulanan jadi satu baris, dan dipakai ulang di mana pun, dari dashboard sampai export excel.

Kesimpulan

  • view itu tabel virtual dari hasil query, data aslinya tetap di tabel sumber
  • CREATE VIEW buat bikin, CREATE OR REPLACE VIEW buat ubah, DROP VIEW buat hapus
  • view menyederhanakan query join berulang dan bikin laporan konsisten
  • view juga alat keamanan, batasi kolom sensitif dari user tertentu
  • view sederhana bisa di-insert, update, delete, dan pasang WITH CHECK OPTION biar aman
  • mysql tidak punya materialized view, performa view tergantung query di dalamnya

Baca Juga Mengenai :


Pertanyaan yang Sering Diajukan

Apa itu view di MySQL?

view itu tabel virtual hasil query select. view tidak nyimpen data sendiri, tiap kali diakses dia jalanin query-nya ke tabel asli. fungsinya nyederhanain query kompleks, ngamanin data, dan bikin laporan lebih konsisten.

Apa bedanya view dan tabel biasa?

tabel nyimpen data fisik di disk, view cuma nyimpen query. jadi kalau data di tabel asli berubah, hasil view langsung ikut berubah tanpa perlu diupdate manual. ukuran view juga kecil karena cuma definisi.

Apakah view di MySQL bisa di-insert, update, atau delete?

bisa, selama view-nya updatable, artinya query-nya tidak pakai group by, distinct, union, join ke banyak tabel yang bikin baris ambigu, atau fungsi agregat. kalau cuma select sederhana dari satu tabel, biasanya aman.

Bagaimana cara update atau hapus view?

update pakai CREATE OR REPLACE VIEW, hapus pakai DROP VIEW IF EXISTS nama_view, dan lihat definisinya pakai SHOW CREATE VIEW nama_view.

Apa itu WITH CHECK OPTION di view?

WITH CHECK OPTION maksa semua data yang masuk lewat view memenuhi kondisi where di view. tanpa ini, data yang tidak lolos kondisi tetap bisa masuk tapi langsung tidak kelihatan di view, bikin bingung.

Apakah MySQL punya materialized view?

tidak. mysql cuma punya view biasa yang dihitung tiap kali diakses. kalau butuh hasil yang disimpan fisik, emulasi pakai tabel biasa yang di-refresh pakai event scheduler atau trigger.

Kenapa view bisa bikin query lambat?

karena view itu query di dalam query. kalau view-nya join banyak tabel lalu di-join lagi dengan filter di luar, mysql harus proses semua baris dulu. solusinya sederhanakan view, jangan menumpuk view di atas view.

Sigit Nurhanafi avatar
Full-stack developer & technical writer. Berpengalaman di PHP, Laravel, NodeJS, MySQL, dan Python. Aktif menulis tutorial pemrograman dan maintaining open-source projects di PemburuKode sejak 2021.