Database yang dipakai bertahun-tahun mudah menumpuk view lama: view laporan proyek yang sudah ditutup, view perantara yang definisinya sudah berubah tiga kali, view uji coba yang tidak pernah dibersihkan. View yang tidak terpakai bukan barang mati — view tetap muncul di SHOW TABLES, bisa bentrok nama dengan objek baru, dan tetap menipu pembaca seolah menyediakan data yang relevan. Housekeeping view memakai satu statement saja: DROP VIEW. Pada chapter ini kita latih penghapusan satu view, banyak view sekaligus, penanganan error ketika nama tidak ditemukan, lalu satu kasus paling berbahaya: menghapus view induk ketika masih ada view anak yang dibangun di atasnya.
Menyiapkan Tabel dan Beberapa View Latihan #
Kita siapkan kembali database belajar_view dengan tabel karyawan delapan baris dan tiga view dengan peran berbeda — dua view penyaring departemen dan satu view laporan agregat:
DROP DATABASE IF EXISTS belajar_view;
CREATE DATABASE belajar_view;
USE belajar_view;Output yang Dihasilkan:
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 1 row affected (0.00 sec)
Database changedCREATE TABLE karyawan (
id INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(60) NOT NULL,
gaji DECIMAL(10,2) NOT NULL,
departemen VARCHAR(30) NOT NULL,
tanggal_masuk DATE NOT NULL
);
INSERT INTO karyawan (nama, gaji, departemen, tanggal_masuk) VALUES
('Budi Santoso', 8500000.00, 'IT', '2021-03-01'),
('Siti Rahayu', 7200000.00, 'IT', '2022-07-15'),
('Andi Wijaya', 9500000.00, 'Keuangan', '2020-01-20'),
('Dewi Lestari', 6800000.00, 'Keuangan', '2023-02-10'),
('Rina Kurnia', 5500000.00, 'HR', '2023-09-05'),
('Tono Prasetyo', 7700000.00, 'IT', '2021-11-01'),
('Sari Wulandari', 6300000.00, 'HR', '2024-01-08'),
('Joko Susilo', 8900000.00, 'Pemasaran', '2022-04-12');
CREATE VIEW v_karyawan_it AS
SELECT id, nama, gaji FROM karyawan WHERE departemen = 'IT';
CREATE VIEW v_karyawan_keuangan AS
SELECT id, nama, gaji FROM karyawan WHERE departemen = 'Keuangan';
CREATE VIEW v_rekap_departemen AS
SELECT departemen, COUNT(*) AS jumlah_karyawan, SUM(gaji) AS total_gaji
FROM karyawan GROUP BY departemen;
SHOW FULL TABLES;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
Query OK, 8 rows affected (0.00 sec)
Records: 8 Duplicates: 0 Warnings: 0
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
+------------------------+------------+
| Tables_in_belajar_view | Table_type |
+------------------------+------------+
| karyawan | BASE TABLE |
| v_karyawan_it | VIEW |
| v_karyawan_keuangan | VIEW |
| v_rekap_departemen | VIEW |
+------------------------+------------+
4 rows in set (0.00 sec)Kolom Table_type mengonfirmasi empat objek dalam database ini: satu BASE TABLE bernama karyawan dan tiga VIEW. Seluruh contoh penghapusan berikutnya beraksi pada ketiga view itu, sementara tabel karyawan beserta delapan baris datanya menjadi saksi bahwa penghapusan view tidak pernah menyentuh data.
Menghapus Satu View #
Penghapusan satu view memakai bentuk paling sederhana dari statement DROP VIEW:
DROP VIEW v_karyawan_keuangan;
SHOW FULL TABLES;
SELECT COUNT(*) AS jumlah_baris_tabel FROM karyawan;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
+------------------------+------------+
| Tables_in_belajar_view | Table_type |
+------------------------+------------+
| karyawan | BASE TABLE |
| v_karyawan_it | VIEW |
| v_rekap_departemen | VIEW |
+------------------------+------------+
3 rows in set (0.00 sec)
+--------------------+
| jumlah_baris_tabel |
+--------------------+
| 8 |
+--------------------+
1 row in set (0.00 sec)Hasilnya lugas: view v_karyawan_keuangan lenyap dari daftar objek — tersisa v_karyawan_it dan v_rekap_departemen — sementara SELECT COUNT(*) ke tabel karyawan tetap mengembalikan delapan baris. Statement penghapusan hanya membuang definisi query yang tersimpan di katalog server; tidak ada baris data yang ikut terhapus karena memang tidak pernah ada data yang disimpan di dalam view. Perilaku ini berbeda total dari DROP TABLE, yang benar-benar membuang struktur sekaligus isi tabel dari disk.
Ketika View Tidak Ada: ERROR 1051 dan Pola IF EXISTS #
Menghapus objek yang memang sudah tidak ada adalah kekeliruan yang hampir pasti kita alami — entah karena view memang sudah dihapus di sesi sebelumnya, atau namanya salah ketik. MySQL menolak statement tersebut:
-- @error
DROP VIEW v_karyawan_keuangan;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
ERROR 1051 (42S02): Unknown table 'belajar_view.v_karyawan_keuangan'
ByeServer menjawab ERROR 1051 (42S02): Unknown table 'belajar_view.v_karyawan_keuangan'. Perhatikan pilihan katanya: pesan menyebut “Unknown table” padahal objek yang kita minta adalah view — ini bukan kebetulan aneh, melainkan konsekuensi ruang nama bersama yang sudah kita bahas: bagi server, tabel dan view berbagi satu katalog objek bertipe tabel, sehingga laporan “nama tidak dikenal” memakai satu format pesan yang sama. Untuk skrip yang harus aman dijalankan berulang — misalnya skrip migrasi yang dijalankan tiap rilis — bentuk IF EXISTS mencegah kegagalan ini:
DROP VIEW IF EXISTS v_karyawan_keuangan;
SHOW WARNINGS;Output yang Dihasilkan:
Query OK, 0 rows affected, 1 warning (0.00 sec)
+-------+------+--------------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------------+
| Note | 1051 | Unknown table 'belajar_view.v_karyawan_keuangan' |
+-------+------+--------------------------------------------------+
1 row in set (0.00 sec)Statement kini sukses dengan laporan Query OK, 0 rows affected, 1 warning. SHOW WARNINGS menampilkan isi peringatannya: sebuah Note berkode 1051 yang isinya sama dengan pesan error tadi. Inilah perbedaan perilaku kedua bentuk: tanpa IF EXISTS, nama yang tidak dikenal membatalkan statement dengan error; dengan IF EXISTS, nama yang tidak dikenal diabaikan secara diam-diam dan hanya ditinggalkan sebagai catatan.
Menghapus Banyak View Sekaligus #
DROP VIEW menerima daftar nama yang dipisah koma, sehingga pembersihan massal tidak perlu satu statement per view. Kita hapus dua view tersisa sekaligus:
DROP VIEW v_karyawan_it, v_rekap_departemen;
SHOW FULL TABLES;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
+------------------------+------------+
| Tables_in_belajar_view | Table_type |
+------------------------+------------+
| karyawan | BASE TABLE |
+------------------------+------------+
1 row in set (0.00 sec)Satu statement menjatuhkan kedua view, dan SHOW FULL TABLES kini hanya melaporkan tabel karyawan — ketiga view latihan telah bersih. Daftar panjang pun sah adanya; perintah semacam DROP VIEW v_laporan_a, v_laporan_b, v_laporan_c menjatuhkan ketiganya dalam satu kali komunikasi ke server. Satu catatan penting: statement ini bersifat all-or-nothing per nama yang tidak dikenal — bila salah satu nama di daftar tidak ada, seluruh statement digagalkan sebelum ada yang terhapus (kecuali kita memakai IF EXISTS, yang membuat nama hilang diabaikan).
View yang Menjadi Yatim: Menghapus Induk dari View Bertingkat #
Kasus paling halus terjadi ketika satu view dibangun di atas view lain. Kita buat pasangan bertingkat: v_pegawai_it sebagai view induk, dan v_gaji_tinggi_it sebagai view anak yang membaca dari induknya:
CREATE VIEW v_pegawai_it AS
SELECT id, nama, gaji, departemen FROM karyawan WHERE departemen = 'IT';
CREATE VIEW v_gaji_tinggi_it AS
SELECT id, nama, gaji FROM v_pegawai_it WHERE gaji >= 8000000;
SELECT id, nama, gaji FROM v_gaji_tinggi_it ORDER BY id;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
+----+--------------+------------+
| id | nama | gaji |
+----+--------------+------------+
| 1 | Budi Santoso | 8500000.00 |
+----+--------------+------------+
1 row in set (0.00 sec)View anak bekerja normal: dari tiga pegawai IT, hanya Budi Santoso dengan gaji 8500000.00 yang lolos ambang 8000000. Sekarang kita hapus view induknya:
DROP VIEW v_pegawai_it;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)Penghapusan induk sukses tanpa peringatan apa pun — MySQL tidak menolak, tidak memperingatkan, dan tidak ikut menghapus view anak. Namun begitu view anak digunakan, kondisi sebenarnya terkuak:
-- @error
SELECT * FROM v_gaji_tinggi_it;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)
ERROR 1356 (HY000): View 'belajar_view.v_gaji_tinggi_it' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
ByeServer menolak dengan ERROR 1356 (HY000): View 'belajar_view.v_gaji_tinggi_it' references invalid table(s) or column(s)... — definisi view anak merujuk v_pegawai_it yang sudah tidak ada, tepat seperti view yang merujuk kolom tabel dasar yang dihapus pada chapter sebelumnya. View yang rusak ini masih bisa dibersihkan secara normal, karena DROP VIEW bekerja pada katalog objek, bukan pada query definisinya:
DROP VIEW v_gaji_tinggi_it;Output yang Dihasilkan:
Query OK, 0 rows affected (0.00 sec)Membersihkan Database Latihan #
Seluruh view sudah bersih sejak blok terakhir; kita jatuhkan sisa datanya:
DROP DATABASE belajar_view;Output yang Dihasilkan:
Query OK, 1 row affected (0.00 sec)Referensi #
- DROP VIEW Statement — MySQL 8.4 Reference Manual
- CREATE VIEW Statement — MySQL 8.4 Reference Manual
- View Processing — MySQL 8.4 Reference Manual
Siklus hidup view kini lengkap dari lahir sampai dibersihkan: dibuat dengan CREATE VIEW, diganti dengan CREATE OR REPLACE VIEW atau ALTER VIEW, dan dihapus dengan DROP VIEW beserta pola IF EXISTS untuk skrip idempoten. Namun sepanjang siklus itu kita hanya memakai view sebagai alat baca. Padahal view juga bisa menjadi alat kendali: menyembunyikan kolom sensitif seperti gaji, membatasi baris yang terlihat, bahkan menjadi satu-satunya pintu data bagi user tertentu. Chapter berikutnya membahas view dari sisi keamanan data.