Migrasi Skema — SQL

Migrasi adalah cara mengelola perubahan skema database secara terstruktur — seperti version control untuk database. ALTER TABLE — mengubah tabel yang sudah…

Migrasi adalah perubahan struktur database (menambah kolom, mengganti nama, membuat tabel baru) yang ditulis sebagai langkah berurutan, supaya setiap database (di laptopmu, di laptop temanmu, di server production) bisa menerima perubahan yang sama dengan urutan yang sama, tanpa kehilangan datanya. Bayangin renovasi rumah yang sedang dihuni. Kamu gak merobohkan rumah untuk menambah satu kamar. Kamu menambah kamarnya, penghuninya tetap tinggal, dan tiap renovasi dicatat di buku supaya ketahuan mana yang sudah dikerjakan.

🧪 Tebakan cepat: tabel users sudah berisi Budi dan Siti. Kamu menambah kolom phone. Apa isi phone untuk Budi dan Siti sesudahnya: error, NULL, atau teks kosong? Tebak dulu, jawabannya ada di bagian "Menambah kolom dengan ALTER TABLE".

Kenapa gak DROP lalu CREATE lagi

Di laptopmu, mengubah tabel paling gampang dengan DROP TABLE users; lalu CREATE TABLE users (...) versi baru. Tapi DROP TABLE menghapus semua barisnya. Di server production, itu berarti semua akun penggunamu hilang. Migrasi mengubah struktur tabel sambil membiarkan datanya tetap di tempat. Alatnya ALTER TABLE.

Menambah kolom dengan ALTER TABLE

Ini tabel dari latihan:

CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT);
INSERT INTO users VALUES (1, 'Budi', '[email protected]');
INSERT INTO users VALUES (2, 'Siti', '[email protected]');

Aplikasimu sekarang butuh nomor HP. Tambahkan kolomnya, lalu masukkan pengguna baru yang punya nomor HP:

ALTER TABLE users ADD COLUMN phone TEXT;
INSERT INTO users (name, email, phone) VALUES ('Dewi', '[email protected]', '08123456789');
SELECT * FROM users;
id name email phone
1 Budi [email protected] NULL
2 Siti [email protected] NULL
3 Dewi [email protected] 08123456789

Apa lagi yang bisa ALTER TABLE

ALTER TABLE users RENAME COLUMN phone TO phone_number;  -- ganti nama kolom
ALTER TABLE users DROP COLUMN phone_number;             -- hapus kolom beserta isinya
ALTER TABLE users RENAME TO members;                    -- ganti nama tabel

Tiap database punya bagian ALTER TABLE yang sedikit beda. Yang paling sering bikin bingung adalah mengubah tipe atau aturan kolom yang sudah ada:

Perubahan SQLite MySQL PostgreSQL
Tambah kolom ADD COLUMN ADD COLUMN ADD COLUMN
Ganti nama kolom RENAME COLUMN a TO b RENAME COLUMN a TO b RENAME COLUMN a TO b
Hapus kolom DROP COLUMN DROP COLUMN DROP COLUMN
Ubah tipe atau aturan kolom gak bisa, bangun ulang tabel MODIFY COLUMN nama VARCHAR(200) ALTER COLUMN nama TYPE VARCHAR(200)

SQLite baru bisa DROP COLUMN sejak versi 3.35 (2021), jadi tutorial lama sering bilang gak bisa. Masih ada batasnya: kolom PRIMARY KEY, kolom UNIQUE, dan kolom yang punya index gak bisa dihapus. ADD COLUMN di SQLite juga menolak beberapa hal: kolom NOT NULL tanpa DEFAULT (Cannot add a NOT NULL column with default value NULL) dan kolom UNIQUE (Cannot add a UNIQUE column). MODIFY COLUMN ala MySQL ditolak SQLite dengan near "MODIFY": syntax error.

Bangun ulang tabel di SQLite

Untuk perubahan yang gak bisa dilakukan ALTER TABLE SQLite, misalnya menjadikan email wajib diisi, caranya membangun tabel baru lalu memindahkan datanya:

BEGIN TRANSACTION;
CREATE TABLE users_new (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, email TEXT NOT NULL, phone TEXT);
INSERT INTO users_new (id, name, email, phone) SELECT id, name, email, phone FROM users;
DROP TABLE users;
ALTER TABLE users_new RENAME TO users;
COMMIT;
  1. Buat tabel baru dengan struktur yang diinginkan.
  2. Salin semua baris dari tabel lama dengan INSERT INTO ... SELECT.
  3. Hapus tabel lama.
  4. Ganti nama tabel baru jadi nama lama.

Semuanya di dalam transaksi, supaya kalau satu langkah gagal, ROLLBACK mengembalikan tabel lama utuh. Index dan trigger milik tabel lama ikut terhapus, jadi buat ulang sesudahnya. Laravel melakukan empat langkah ini otomatis waktu kamu mengubah kolom dengan ->change() di SQLite.

Migrasi: perubahan yang tercatat dan berurutan

Di proyek sungguhan, tiap perubahan ditulis sebagai satu file migrasi, dengan nama yang diawali tanggal supaya urutannya jelas. Di Laravel, satu file punya dua bagian: up() untuk menerapkan perubahan, down() untuk membatalkannya.

// database/migrations/2026_10_02_000000_add_phone_to_users.php
public function up(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->string('phone')->nullable(); // jadi ALTER TABLE users ADD COLUMN phone ...
    });
}

public function down(): void
{
    Schema::table('users', function (Blueprint $table) {
        $table->dropColumn('phone'); // jadi ALTER TABLE users DROP COLUMN phone
    });
}

⚠️ Jebakan yang sering ketemu

TL;DR: Migrasi mengubah struktur tabel tanpa membuang datanya, dengan ALTER TABLE. ADD COLUMN phone TEXT menambah kolom, dan baris lama mendapat NULL. RENAME COLUMN mengganti nama, DROP COLUMN menghapus kolom beserta isinya. Mengubah tipe atau aturan kolom ditulis MODIFY COLUMN di MySQL dan ALTER COLUMN ... TYPE di PostgreSQL, sedangkan SQLite harus membangun ulang tabelnya (buat baru, salin, hapus lama, ganti nama) di dalam transaksi. Di proyek, tiap perubahan jadi file migrasi berurutan dengan up() dan down(), dan tabel migrations mencatat mana yang sudah jalan.

Yang akan kamu pelajari