Обикновено, ако трябва да пуснете външен ключ в SQL, ще използвате ALTER TABLE
изявление. Но ако използвате SQLite, това не е опция.
SQLite поддържа много ограничено подмножество от ALTER TABLE
изявление. Единствените неща, които можете да правите с ALTER TABLE
в SQLite е преименуване на таблица, преименуване на колона в таблица или добавяне на нова колона към съществуваща таблица.
С други думи, не можете да използвате ALTER TABLE
за да пуснете външен ключ, както можете в други RDBMS
Препоръчителният начин да „изпуснете“ външен ключ в SQLite всъщност е да прехвърлите данните в нова таблица без външен ключ (или с различен, ако това е, което ви трябва).
Препоръчителният начин
Документацията на SQLite препоръчва процес от 12 стъпки за промяна на схемата в таблица. Ще използваме този процес, за да „пуснем“ външен ключ в следващия пример.
Създайте таблица с външен ключ
Първо, нека създадем таблица с външния ключ и да я попълним с данни.
CREATE TABLE Types(
TypeId INTEGER PRIMARY KEY,
Type
);
CREATE TABLE Pets(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId,
FOREIGN KEY(TypeId) REFERENCES Types(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 );
Всъщност тук създадох две таблици и ги попълних с данни. Две таблици, защото първата (Типове ) има първичен ключ, а другият (Домашни любимци ) има външния ключ. Външният ключ беше добавен на последния ред на втората таблица.
Можем да проверим дали външният ключ е създаден, като изпълним следната команда:
PRAGMA foreign_key_list(Pets);
Резултат:
id seq table from to on_update on_delete match -- --- ----- ------ ------ --------- --------- ----- 0 0 Types TypeId TypeId NO ACTION NO ACTION NONE
Можем да видим подробностите за ограничението на външния ключ.
Сега нека „пуснем“ външния ключ.
„Хвърлете“ външния ключ
Следният код „изпуска“ външния ключ чрез създаване на нова таблица без ограничение за външен ключ, прехвърляне на данните към тази таблица, премахване на оригиналната таблица и след това преименуване на новата таблица на името на оригиналната таблица.
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
CREATE TABLE Pets_new(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId
);
INSERT INTO Pets_new SELECT * FROM Pets;
DROP TABLE Pets;
ALTER TABLE Pets_new RENAME TO Pets;
COMMIT;
PRAGMA foreign_keys = ON;
Готово.
Ако трябва да реконструирате някакви индекси, тригери или изгледи, направете това след ALTER TABLE
оператор, който преименува таблицата (точно преди COMMIT
).
Сега нека отново проверим таблицата за ограничения на външния ключ.
PRAGMA foreign_key_list(Pets);
Резултат:
(Това е празно, защото в тази таблица няма ограничения за външни ключове.)
Можете да използвате същия метод, за да добавите външен ключ към съществуваща таблица.
Алтернативен метод
Когато разглеждате предишния пример, може да си помислите, че има по-ефективен начин да го направите. Например можете да го направите така:
PRAGMA foreign_keys = OFF;
BEGIN TRANSACTION;
ALTER TABLE Pets RENAME TO Pets_old;
CREATE TABLE Pets(
PetId INTEGER PRIMARY KEY,
PetName,
TypeId
);
INSERT INTO Pets SELECT * FROM Pets_old;
DROP TABLE Pets_old;
COMMIT;
PRAGMA foreign_keys = ON;
И е вярно. С моя пример този метод работи също толкова добре.
Но този метод също има потенциал да повреди препратките към таблицата във всички съществуващи задействания, изгледи и ограничения на външния ключ.
Така че, ако вашата таблица вече има съществуващи задействания, изгледи или ограничения за външен ключ, вероятно е по-безопасно да използвате препоръчания метод.