SQLite mendukung subset yang sangat terbatas dari ALTER TABLE
penyataan. Satu-satunya hal yang dapat Anda lakukan dengan ALTER TABLE
di SQLite adalah mengganti nama tabel, mengganti nama kolom di dalam tabel, atau menambahkan kolom baru ke tabel yang sudah ada.
Dengan kata lain, Anda tidak dapat menggunakan ALTER TABLE
untuk menambahkan kunci asing ke tabel yang ada seperti yang Anda bisa lakukan di sistem manajemen basis data lainnya.
Oleh karena itu, satu-satunya cara Anda dapat “menambahkan” kunci asing ke tabel yang ada di SQLite adalah dengan membuat tabel baru dengan kunci asing, lalu mentransfer data ke tabel baru.
Ada lebih dari satu cara untuk melakukannya, tetapi ada cara yang disarankan.
Cara yang Disarankan
Dokumentasi SQLite merekomendasikan proses 12 langkah untuk membuat perubahan skema ke tabel.
Untuk keperluan artikel ini, kami hanya akan berurusan dengan menambahkan kunci asing.
Untuk membuatnya agak realistis, kami akan memastikan tabel sudah berisi data.
Tabel Asli Tanpa Kunci Asing
Pertama, mari kita buat tabel tanpa kunci asing dan mengisinya dengan data.
CREATE TABLE Types(
TypeId INTEGER PRIMARY KEY,
Type
);
CREATE TABLE Pets(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId
);
INSERT INTO Types VALUES
( NULL, 'Dog' ),
( NULL, 'Cat' ),
( NULL, 'Parakeet' ),
( NULL, 'Hamster' );
INSERT INTO Pets VALUES
( NULL, 'Brush', 3 ),
( NULL, 'Tweet', 3 ),
( NULL, 'Yelp', 1 ),
( NULL, 'Woofer', 1 ),
( NULL, 'Fluff', 2 );
Sebenarnya, di sini saya membuat dua tabel dan mengisinya dengan data. Dua tabel, karena satu (Jenis ) akan memiliki kunci utama dan yang lainnya (Hewan peliharaan ) akan memiliki kunci asing.
Perhatikan bahwa saya tidak membuat kunci asing.
Kami dapat memverifikasi bahwa tidak ada kunci asing dengan menjalankan perintah berikut:
PRAGMA foreign_key_list(Pets);
Dalam kasus saya, saya mendapatkan hasil berikut:
(Itu kosong karena tidak ada batasan kunci asing di tabel ini.)
Sekarang mari kita “tambahkan” kunci asing.
Tambahkan Kunci Asing
Kode berikut menambahkan kunci asing ke tabel kita dengan membuat tabel baru dengan batasan kunci asing, mentransfer data ke tabel itu, menghapus tabel asli, lalu mengganti nama tabel baru dengan nama tabel asli.
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
CREATE TABLE Pets_new(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId,
FOREIGN KEY(TypeId) REFERENCES Types(TypeId)
);
INSERT INTO Pets_new SELECT * FROM Pets;
DROP TABLE Pets;
ALTER TABLE Pets_new RENAME TO Pets;
COMMIT;
PRAGMA foreign_keys = ON;
Selesai.
Jika Anda perlu merekonstruksi indeks, pemicu, atau tampilan apa pun, lakukan setelah ALTER TABLE
pernyataan yang mengganti nama tabel (tepat sebelum COMMIT
).
Sekarang mari kita periksa tabel untuk batasan kunci asing lagi.
.mode line
PRAGMA foreign_key_list(Pets);
Hasil (menggunakan keluaran vertikal):
id = 0 seq = 0 table = Types from = TypeId to = TypeId on_update = NO ACTION on_delete = NO ACTION match = NONE
Kali ini kita bisa melihat detail dari batasan kunci asing.
Perhatikan bahwa baris pertama dari perintah saya (.mode line
) tidak ada hubungannya dengan membuat kunci asing. Saya meletakkannya di sana hanya untuk mengubah cara terminal saya mengeluarkan hasilnya (sehingga Anda tidak perlu menggulir ke samping untuk melihat hasilnya).
Metode Alternatif
Saat melihat contoh sebelumnya, Anda mungkin berpikir bahwa ada cara yang lebih efisien untuk melakukannya. Misalnya Anda bisa melakukannya seperti ini:
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
ALTER TABLE Pets RENAME TO Pets_old;
CREATE TABLE Pets(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId,
FOREIGN KEY(TypeId) REFERENCES Types(TypeId)
);
INSERT INTO Pets SELECT * FROM Pets_old;
DROP TABLE Pets_old;
COMMIT;
PRAGMA foreign_keys = ON;
Dan itu benar. Dengan contoh saya, metode ini bekerja dengan baik.
Namun metode ini juga berpotensi merusak referensi ke tabel di pemicu, tampilan, dan batasan kunci asing yang ada.
Jadi, jika tabel Anda sudah memiliki pemicu, tampilan, atau batasan kunci asing, mungkin lebih aman menggunakan metode yang disarankan.