Резюме :в този урок ще научите как да използвате ограничението на външния ключ на SQLite, за да наложите връзките между свързани таблици.
Поддръжка на ограничения на външния ключ на SQLite
SQLite поддържа ограничение на външния ключ от версия 3.6.19. Библиотеката SQLite също трябва да бъде компилирана нито с SQLITE_OMIT_FOREIGN_KEY, нито с SQLITE_OMIT_TRIGGER.
За да проверите дали текущата ви версия на SQLite поддържа ограничения на външния ключ или не, използвайте следната команда.
PRAGMA foreign_keys;
Code language: SQL (Structured Query Language) (sql)
Командата връща цяло число:1:активиране, 0:деактивирано. Ако командата не връща нищо, това означава, че вашата версия на SQLite не поддържа ограничения за външни ключове.
Ако библиотеката на SQLite е компилирана с поддръжка за ограничаване на външния ключ, приложението може да използва PRAGMA foreign_keys
команда за активиране или деактивиране на ограниченията на външния ключ по време на изпълнение.
За да деактивирате ограничаването на външния ключ:
PRAGMA foreign_keys = OFF;
Code language: SQL (Structured Query Language) (sql)
За да активирате ограничение на външния ключ:
PRAGMA foreign_keys = ON;
Code language: SQL (Structured Query Language) (sql)
Въведение в ограниченията на външния ключ на SQLite
Нека започнем с две таблици:suppliers
и supplier_groups
:
CREATE TABLE suppliers (
supplier_id integer PRIMARY KEY,
supplier_name text NOT NULL,
group_id integer NOT NULL
);
CREATE TABLE supplier_groups (
group_id integer PRIMARY KEY,
group_name text NOT NULL
);
Code language: SQL (Structured Query Language) (sql)
Ако приемем, че всеки доставчик принадлежи към една и само една група доставчици. И всяка група доставчици може да има нула или много доставчици. Връзката между supplier_groups
и suppliers
таблици е едно към много. С други думи, за всеки ред в suppliers
таблица, има съответен ред в supplier_groups
таблица.
Понастоящем няма начин да ви попречим да добавите ред към suppliers
таблица без съответен ред в supplier_groups
таблица.
В допълнение, можете да премахнете ред в supplier_groups
таблица без изтриване или актуализиране на съответните редове в suppliers
маса. Това може да остави осиротели редове в suppliers
таблица.
За да наложите връзката между редовете в suppliers
и supplier_groups
таблица, използвате ограниченията на външния ключ .
За да добавите ограничението на външния ключ към suppliers
таблица, променяте дефиницията на CREATE TABLE
изявление по-горе, както следва:
DROP TABLE suppliers;
CREATE TABLE suppliers (
supplier_id INTEGER PRIMARY KEY,
supplier_name TEXT NOT NULL,
group_id INTEGER NOT NULL,
FOREIGN KEY (group_id)
REFERENCES supplier_groups (group_id)
);
Code language: SQL (Structured Query Language) (sql)
supplier_groups
таблицата се наричародителска таблица , което е таблицата, която препраща външният ключ. suppliers
таблицата е известна като детска маса , което е таблицата, към която се прилага ограничението за външния ключ.
group_id
колона в supplier_groups
таблицата се нарича родителски ключ , което е колона или набор от колони в родителската таблица, към която се позовава ограничението на външния ключ. Обикновено родителският ключ е първичният ключ на родителската таблица.
group_id
колона в suppliers
таблицата се нарича дъщерен ключ. Като цяло, дъщерният ключ се позовава на първичния ключ на родителската таблица.
Пример за ограничение на външния ключ в SQLite
Първо, поставете три реда в supplier_groups
таблица.
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
Второ, поставете нов доставчик в suppliers
таблица с групата на доставчиците, която съществува в supplier_groups
таблица.
INSERT INTO suppliers (supplier_name, group_id)
VALUES ('HP', 2);
Code language: SQL (Structured Query Language) (sql)
Това твърдение работи перфектно.
Трето, опитайте се да вмъкнете нов доставчик в suppliers
таблица с групата на доставчиците, която не съществува в supplier_groups
таблица.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('ABC Inc.', 4);
Code language: SQL (Structured Query Language) (sql)
SQLite провери ограничението на външния ключ, отхвърли промяната и издаде следното съобщение за грешка:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
Действия за ограничаване на външния ключ на SQLite
Какво ще се случи, ако изтриете ред в supplier_groups
маса? Трябва ли всички съответни редове в suppliers
таблицата също се изтриват? Същите въпроси към операцията за актуализиране.
За да посочите как се държи ограничението на външния ключ всеки път, когато родителският ключ бъде изтрит или актуализиран, използвате ON DELETE
или ON UPDATE
действие, както следва:
FOREIGN KEY (foreign_key_columns)
REFERENCES parent_table(parent_key_columns)
ON UPDATE action
ON DELETE action;
Code language: SQL (Structured Query Language) (sql)
SQLite поддържа следните действия:
- ЗАДАВАНЕ НА NULL
- ЗАДАВАНЕ ПО ПОДРАЗБИРАНЕ
- ОГРАНИЧАВАНЕ
- БЕЗ ДЕЙСТВИЕ
- КАСКАДА
На практика стойностите на първичния ключ в родителската таблица не се променят, следователно правилата за актуализиране са по-малко важни. По-важното правило е DELETE
правило, което определя действието при изтриване на родителския ключ.
Ще разгледаме всяко действие чрез следния пример
ЗАДАВАНЕ НА NULL
Когато родителският ключ се промени, изтрие или актуализира, съответните дъщерни ключове на всички редове в дъщерната таблица се задават на NULL.
Първо пуснете и създайте таблицата suppliers
като използвате SET NULL
действие за group_id
външен ключ:
DROP TABLE suppliers;
CREATE TABLE suppliers (
supplier_id INTEGER PRIMARY KEY,
supplier_name TEXT NOT NULL,
group_id INTEGER,
FOREIGN KEY (group_id)
REFERENCES supplier_groups (group_id)
ON UPDATE SET NULL
ON DELETE SET NULL
);
Code language: SQL (Structured Query Language) (sql)
Второ, поставете няколко реда в suppliers
таблица:
INSERT INTO suppliers (supplier_name, group_id)
VALUES('XYZ Corp', 3);
INSERT INTO suppliers (supplier_name, group_id)
VALUES('ABC Corp', 3);
Code language: SQL (Structured Query Language) (sql)
Трето, изтрийте идентификатора на групата на доставчиците 3 от supplier_groups
таблица:
DELETE FROM supplier_groups
WHERE group_id = 3;
Code language: SQL (Structured Query Language) (sql)
Четвърто, потърсете данни от suppliers
таблица.
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Стойностите на group_id
колона на съответните редове в suppliers
таблицата е зададена на NULL.
ЗАДАВАНЕ ПО ПОДРАЗБИРАНЕ
SET DEFAULT
action задава стойността на външния ключ на стойността по подразбиране, посочена в дефиницията на колоната, когато създавате таблицата.
Тъй като стойностите в колоната group_id
по подразбиране е NULL, ако изтриете ред от supplier_groups
таблица, стойностите на group_id
ще бъде зададено на NULL.
След присвояване на стойността по подразбиране, ограничението на външния ключ се включва и носи проверката.
ОГРАНИЧВАНЕ
RESTRICT
действието не ви позволява да променяте или изтривате стойности в родителския ключ на родителската таблица.
Първо, пуснете и създайте suppliers
таблица с RESTRICT
действие във външния ключ group_id
:
DROP TABLE suppliers;
CREATE TABLE suppliers (
supplier_id INTEGER PRIMARY KEY,
supplier_name TEXT NOT NULL,
group_id INTEGER,
FOREIGN KEY (group_id)
REFERENCES supplier_groups (group_id)
ON UPDATE RESTRICT
ON DELETE RESTRICT
);
Code language: SQL (Structured Query Language) (sql)
Второ, поставете ред в таблицата suppliers
с group_id 1.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('XYZ Corp', 1);
Code language: SQL (Structured Query Language) (sql)
Трето, изтрийте групата на доставчиците с идентификатор 1 от supplier_groups
таблица:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
SQLite издаде следната грешка:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
За да го поправите, първо трябва да изтриете всички редове от suppliers
таблица, която има group_id
1:
DELETE FROM suppliers
WHERE group_id =1;
Code language: SQL (Structured Query Language) (sql)
След това можете да изтриете групата на доставчиците 1 от supplier_groups
таблица:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
БЕЗ ДЕЙСТВИЕ
NO ACTION
не означава заобикаляне на ограничението за външния ключ. Той има подобен ефект като RESTRICT
.
КАСКАДА
CASCADE
action разпространява промените от родителската таблица към дъщерната таблица, когато актуализирате или изтриете родителския ключ.
Първо поставете supplier
групи в supplier_groups
таблица:
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
Второ, пуснете и създайте таблицата suppliers
с CASCADE
действие във външния ключ group_id
:
DROP TABLE suppliers;
CREATE TABLE suppliers (
supplier_id INTEGER PRIMARY KEY,
supplier_name TEXT NOT NULL,
group_id INTEGER,
FOREIGN KEY (group_id)
REFERENCES supplier_groups (group_id)
ON UPDATE CASCADE
ON DELETE CASCADE
);
Code language: SQL (Structured Query Language) (sql)
Трето, вмъкнете някои доставчици в таблицата suppliers
:
INSERT INTO suppliers (supplier_name, group_id)
VALUES('XYZ Corp', 1);
INSERT INTO suppliers (supplier_name, group_id)
VALUES('ABC Corp', 2);
Code language: SQL (Structured Query Language) (sql)
Четвърто, актуализирайте group_id
на Domestic
група доставчици до 100:
UPDATE supplier_groups
SET group_id = 100
WHERE group_name = 'Domestic';
Code language: SQL (Structured Query Language) (sql)
Пето, потърсете данни от таблицата suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Както можете да видите стойността в group_id
колона на XYZ Corp
в таблицата suppliers
се промени от 1 на 100, когато актуализирахме group_id
в supplier_groups
маса. Това е резултатът от ON UPDATE CASCADE
действие.
Шесто, изтрийте идентификатор на групата на доставчиците 2 от supplier_groups
таблица:
DELETE FROM supplier_groups
WHERE group_id = 2;
Code language: SQL (Structured Query Language) (sql)
Седмо, заявете данни от таблицата suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Идентификаторът на доставчика 2, чийто group_id
е 2 беше изтрит, когато идентификаторът на групата на доставчиците 2 беше премахнат от supplier_groups
маса. Това е ефектът от ON DELETE CASCADE
действие.
В този урок научихте за ограниченията на външния ключ на SQLite и как да ги използвате, за да наложите връзката между свързани таблици.