Skema Bisa Berubah, dan SQLite Mengizinkannya (Sebagian Besar)
Begitu sebuah tabel ada, cepat atau lambat kamu akan ingin mengganti namanya, menambah kolom, menghapus kolom, atau menyusun ulang seluruhnya. SQLite mendukung kasus-kasus umum secara langsung dengan DROP TABLE dan ALTER TABLE, dan memberimu solusi yang terdokumentasi untuk sisanya.
Kekurangannya: ALTER TABLE di SQLite jauh lebih terbatas dibanding Postgres atau MySQL. Mengetahui apa yang bisa dan tidak bisa dilakukannya, serta pola membangun ulang untuk yang tidak bisa, adalah sebagian besar keterampilan di sini.
DROP TABLE Menghapus Tabel dan Semua yang Melekat Padanya
DROP TABLE menghapus tabel, baris-barisnya, index-nya, dan trigger apa pun yang didefinisikan padanya. Tidak ada undo:
Tabelnya sudah hilang. Menjalankan query ke tabel itu sekarang akan memunculkan no such table: scratch.
Kalau kamu tidak yakin tabelnya ada, yang sering terjadi di skrip setup, pakai IF EXISTS agar pernyataannya diam-diam tidak melakukan apa-apa saat tabelnya tidak ada:
Tanpa IF EXISTS, penghapusan kedua akan error. Dengan itu, keduanya berjalan lancar.
Foreign Key Bisa Menghalangi DROP
Kalau penegakan foreign key aktif (PRAGMA foreign_keys = ON;) dan ada tabel lain yang merujuk tabel yang akan kamu hapus, penghapusannya gagal:
sqlite> PRAGMA foreign_keys = ON;
sqlite> DROP TABLE users;
Runtime error: FOREIGN KEY constraint failed
Kamu punya beberapa pilihan: hapus tabel yang merujuk lebih dulu, hapus baris yang merujuk, atau definisikan foreign key dengan ON DELETE CASCADE saat membuatnya. SQLite tidak akan diam-diam merusak integritas referensial untukmu.
ALTER TABLE: Empat Hal yang Bisa Dilakukannya
ALTER TABLE di SQLite mendukung tepat empat operasi:
Masing-masing berjalan sebagai satu pernyataan. Dua yang pertama pada dasarnya gratis, karena hanya memperbarui skema. ADD COLUMN juga cepat: SQLite tidak menulis ulang tabel, ia hanya mencatat definisi kolom yang baru. DROP COLUMN lebih berat, karena SQLite harus menulis ulang setiap baris untuk benar-benar menghapus data kolom itu.
ADD COLUMN dengan Nilai Default
Kolom baru pada tabel yang sudah ada dimulai dengan nilai NULL di setiap baris, kecuali kamu memberinya nilai default:
Kedua baris yang sudah ada terisi 'active'. Nilai default-nya harus berupa konstanta: SQLite tidak mengizinkanmu memakai CURRENT_TIMESTAMP atau ekspresi non-konstan lain sebagai default di ADD COLUMN, karena ia butuh nilai yang bisa diterapkan ke setiap baris yang ada tanpa dievaluasi per baris.
Kalau kamu butuh NOT NULL tanpa nilai default, kamu harus menambahkan kolomnya sebagai nullable, mengisinya dengan UPDATE, lalu membangun ulang tabel untuk menambahkan constraint-nya. Itu membawa kita ke batasannya.
Apa yang Tidak Bisa Dilakukan ALTER TABLE
Hal-hal yang bisa di Postgres atau MySQL tapi tidak di SQLite:
- Mengubah tipe kolom (
ALTER COLUMN ... TYPE ...). - Mengubah nilai default kolom di tempat.
- Menambah atau menghapus
NOT NULL,CHECK,UNIQUE, atauPRIMARY KEYpada kolom yang sudah ada. - Menambahkan foreign key ke kolom yang sudah ada.
- Mengubah urutan kolom.
Mencoba salah satunya akan memberimu syntax error. SQLite sama sekali tidak punya klausa ALTER COLUMN. Jawaban resminya sama untuk semuanya: bangun ulang tabelnya.
Pola Membangun Ulang Tabel
Kalau ALTER TABLE tidak bisa melakukan yang kamu butuhkan, buat tabel baru dengan skema yang kamu inginkan, salin datanya, hapus tabel lama, lalu ganti nama tabel baru ke nama lama. Bungkus dalam transaksi agar semuanya berhasil atau tidak sama sekali:
Sekarang users.age adalah integer dengan check constraint, dan email bersifat NOT NULL. Datanya ikut terbawa.
Beberapa hal yang perlu diingat saat kamu melakukannya sungguhan:
- Matikan foreign key selama prosesnya. Kalau ada tabel lain yang merujuk tabelmu, jalankan
PRAGMA foreign_keys = OFF;sebelum transaksi danPRAGMA foreign_keys = ON;sesudahnya. Kalau tidak,DROP TABLEakan gagal. Pragma ini tidak bisa diubah di dalam transaksi, jadi atur di luarnya. - Buat ulang index dan trigger. Menghapus tabel lama juga menghapus index dan trigger-nya. Tambahkan kembali pada tabel baru setelah penggantian nama.
- Periksa view. View yang merujuk tabel itu masih menunjuk ke nama lama di SQL yang tersimpan. Bangun ulang view yang bergantung pada kolom yang berubah.
Pola membangun ulang memang panjang, tapi bisa diandalkan. Inilah yang dilakukan tool migrasi seperti Alembic dan Rails di balik layar saat menargetkan SQLite.
Menghapus Beberapa Tabel
Tidak ada satu pernyataan untuk menghapus beberapa tabel sekaligus: kamu menjalankan DROP TABLE untuk masing-masing. Taruh di dalam transaksi kalau kamu ingin semuanya dikelompokkan:
Membungkusnya dalam transaksi berarti ketiga penghapusan berhasil semua atau tidak ada yang berhasil. Ini berguna saat membongkar tabel-tabel terkait yang mungkin gagal di tengah jalan karena foreign key.
Yang Perlu Kamu Ingat
DROP TABLEmenghapus tabel beserta index dan trigger-nya. PakaiIF EXISTSuntuk skrip yang aman dijalankan berulang.ALTER TABLEhanya melakukan empat hal: ganti nama tabel, ganti nama kolom, tambah kolom, hapus kolom.- Untuk hal lainnya, seperti perubahan tipe, constraint baru, atau foreign key pada kolom yang sudah ada, bangun ulang tabel di dalam transaksi.
- Perhatikan foreign key, index, trigger, dan view saat membangun ulang. Semuanya tidak otomatis ikut bersama data.
Berikutnya: Memasukkan Data
Kamu sudah menghabiskan satu bab untuk tabel dan constraint yang membentuknya. Saatnya mengisinya: bab berikutnya dimulai dengan INSERT, termasuk bentuk banyak baris, nilai default, dan cara SQLite menangani insert yang bentrok dengan constraint-mu.
Pertanyaan yang sering diajukan
Bagaimana cara menghapus tabel di SQLite?
Pakai DROP TABLE table_name;. Tambahkan IF EXISTS agar tidak melakukan apa-apa kalau tabelnya tidak ada: DROP TABLE IF EXISTS users;. Menghapus tabel juga menghapus index dan trigger-nya, dan kalau foreign key ditegakkan, penghapusan gagal selama masih ada tabel lain yang merujuknya.
Apa saja yang bisa dilakukan ALTER TABLE di SQLite?
Empat hal: RENAME TO (mengganti nama tabel), RENAME COLUMN ... TO ... (mengganti nama kolom), ADD COLUMN (menambah kolom baru), dan DROP COLUMN (menghapus kolom, sejak SQLite 3.35). Hanya itu: kamu tidak bisa mengubah tipe kolom, mengubah nilai default-nya di tempat, atau menambahkan constraint ke kolom yang sudah ada.
Bagaimana cara mengubah tipe atau constraint sebuah kolom di SQLite?
SQLite tidak mendukungnya secara langsung. Solusi standarnya adalah pola membangun ulang: buat tabel baru dengan skema yang kamu inginkan, INSERT INTO new SELECT ... FROM old, DROP TABLE old, lalu ALTER TABLE new RENAME TO old. Bungkus semuanya dalam transaksi agar bersifat atomik.