Podsumowanie :w tym samouczku dowiesz się, jak używać ograniczenia klucza obcego SQLite do wymuszania relacji między powiązanymi tabelami.
Obsługa ograniczeń klucza obcego SQLite
SQLite obsługuje ograniczenie klucza obcego od wersji 3.6.19. Biblioteka SQLite musi być również skompilowana bez SQLITE_OMIT_FOREIGN_KEY ani SQLITE_OMIT_TRIGGER.
Aby sprawdzić, czy twoja aktualna wersja SQLite obsługuje ograniczenia klucza obcego, czy nie, użyj następującego polecenia.
PRAGMA foreign_keys;
Code language: SQL (Structured Query Language) (sql)
Polecenie zwraca wartość całkowitą:1:włącz, 0:wyłącz. Jeśli polecenie nic nie zwraca, oznacza to, że twoja wersja SQLite nie obsługuje ograniczeń kluczy obcych.
Jeśli biblioteka SQLite jest skompilowana z obsługą ograniczeń kluczy obcych, aplikacja może użyć PRAGMA foreign_keys
polecenie, aby włączyć lub wyłączyć ograniczenia klucza obcego w czasie wykonywania.
Aby wyłączyć ograniczenie klucza obcego:
PRAGMA foreign_keys = OFF;
Code language: SQL (Structured Query Language) (sql)
Aby włączyć ograniczenie klucza obcego:
PRAGMA foreign_keys = ON;
Code language: SQL (Structured Query Language) (sql)
Wprowadzenie do ograniczeń kluczy obcych SQLite
Zacznijmy od dwóch tabel:suppliers
i 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)
Przy założeniu, że każdy dostawca należy do jednej i tylko jednej grupy dostawców. Każda grupa dostawców może mieć zero lub wielu dostawców. Związek między supplier_groups
i suppliers
tabele to jeden do wielu. Innymi słowy, dla każdego wiersza w suppliers
tabeli, odpowiedni wiersz znajduje się w supplier_groups
tabela.
Obecnie nie ma sposobu, aby uniemożliwić dodanie wiersza do suppliers
tabela bez odpowiedniego wiersza w supplier_groups
tabela.
Ponadto możesz usunąć wiersz w supplier_groups
tabela bez usuwania lub aktualizowania odpowiednich wierszy w suppliers
stół. Może to pozostawić osierocone wiersze u suppliers
tabela.
Aby wymusić relację między wierszami u suppliers
i supplier_groups
tabeli, używasz ograniczeń kluczy obcych .
Aby dodać ograniczenie klucza obcego do suppliers
tabeli, zmieniasz definicję CREATE TABLE
oświadczenie powyżej w następujący sposób:
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
tabela nazywana jest tablicą nadrzędną , czyli tabela, do której odwołuje się klucz obcy. suppliers
tabela jest znana jako tabela podrzędna , czyli tabela, do której stosuje się ograniczenie klucza obcego.
group_id
kolumna w supplier_groups
tabela nazywa się kluczem nadrzędnym , czyli kolumna lub zestaw kolumn w tabeli nadrzędnej, do której odwołuje się ograniczenie klucza obcego. Zazwyczaj klucz nadrzędny jest kluczem podstawowym tabeli nadrzędnej.
group_id
kolumna w suppliers
tabela nazywana jest kluczem potomnym. Ogólnie klucz potomny odwołuje się do klucza głównego tabeli nadrzędnej.
Przykład ograniczenia klucza obcego SQLite
Najpierw wstaw trzy wiersze do supplier_groups
tabela.
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
Po drugie, wstaw nowego dostawcę do suppliers
tabela z grupą dostawców istniejącą w supplier_groups
tabela.
INSERT INTO suppliers (supplier_name, group_id)
VALUES ('HP', 2);
Code language: SQL (Structured Query Language) (sql)
To stwierdzenie działa doskonale.
Po trzecie, spróbuj wstawić nowego dostawcę do suppliers
tabela z grupą dostawców, która nie istnieje w supplier_groups
tabela.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('ABC Inc.', 4);
Code language: SQL (Structured Query Language) (sql)
SQLite sprawdził ograniczenie klucza obcego, odrzucił zmianę i wysłał następujący komunikat o błędzie:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
Działania ograniczające klucze obce SQLite
Co się stanie, jeśli usuniesz wiersz w supplier_groups
stół? Czy wszystkie odpowiednie wiersze w suppliers
? tabela również została usunięta? Te same pytania dotyczące operacji aktualizacji.
Aby określić, jak zachowuje się ograniczenie klucza obcego, gdy klucz nadrzędny jest usuwany lub aktualizowany, użyj ON DELETE
lub ON UPDATE
działanie w następujący sposób:
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 obsługuje następujące akcje:
- USTAW NULL
- USTAW DOMYŚLNE
- OGRANICZONE
- BRAK DZIAŁANIA
- KASKADA
W praktyce wartości klucza podstawowego w tabeli nadrzędnej nie zmieniają się, dlatego zasady aktualizacji są mniej ważne. Ważniejszą zasadą jest DELETE
reguła określająca akcję po usunięciu klucza nadrzędnego.
Przeanalizujemy każdą akcję na poniższym przykładzie
USTAW NULL
Gdy klucz nadrzędny zostanie zmieniony, usunięty lub zaktualizowany, odpowiednie klucze podrzędne wszystkich wierszy w tabeli podrzędnej zostaną ustawione na NULL.
Najpierw upuść i utwórz tabelę suppliers
używając SET NULL
akcja dla group_id
klucz obcy:
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)
Po drugie, wstaw kilka wierszy do suppliers
tabela:
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)
Po trzecie, usuń identyfikator grupy dostawców 3 z supplier_groups
tabela:
DELETE FROM supplier_groups
WHERE group_id = 3;
Code language: SQL (Structured Query Language) (sql)
Po czwarte, zapytaj o dane od suppliers
tabela.
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Wartości group_id
kolumna odpowiednich wierszy w suppliers
tabela ustawiona na NULL.
USTAW DOMYŚLNE
SET DEFAULT
akcja ustawia wartość klucza obcego na wartość domyślną określoną w definicji kolumny podczas tworzenia tabeli.
Ponieważ wartości w kolumnie group_id
domyślnie NULL, jeśli usuniesz wiersz z supplier_groups
tabeli, wartości group_id
zostanie ustawiony na NULL.
Po przypisaniu wartości domyślnej, ograniczenie klucza obcego uruchamia się i przenosi kontrolę.
OGRANICZ
RESTRICT
akcja nie pozwala na zmianę lub usunięcie wartości w kluczu nadrzędnym tabeli nadrzędnej.
Najpierw upuść i utwórz suppliers
tabela z RESTRICT
akcja w kluczu obcym 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)
Po drugie, wstaw wiersz do tabeli suppliers
z identyfikatorem grupy 1.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('XYZ Corp', 1);
Code language: SQL (Structured Query Language) (sql)
Po trzecie, usuń grupę dostawców o identyfikatorze 1 z supplier_groups
tabela:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
SQLite wysłał następujący błąd:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
Aby to naprawić, musisz najpierw usunąć wszystkie wiersze od suppliers
tabela, która ma group_id
1:
DELETE FROM suppliers
WHERE group_id =1;
Code language: SQL (Structured Query Language) (sql)
Następnie możesz usunąć grupę dostawców 1 z supplier_groups
tabela:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
BRAK DZIAŁANIA
NO ACTION
nie oznacza obejścia ograniczenia klucza obcego. Ma podobny efekt jak RESTRICT
.
KASKADA
CASCADE
akcja propaguje zmiany z tabeli nadrzędnej do tabeli podrzędnej, gdy aktualizujesz lub usuwasz klucz nadrzędny.
Najpierw wstaw supplier
grup w supplier_groups
tabela:
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
Po drugie, upuść i utwórz tabelę suppliers
z CASCADE
akcja w kluczu obcym 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)
Po trzecie, wstaw niektórych dostawców do tabeli 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)
Po czwarte, zaktualizuj group_id
Domestic
grupa dostawców do 100:
UPDATE supplier_groups
SET group_id = 100
WHERE group_name = 'Domestic';
Code language: SQL (Structured Query Language) (sql)
Po piąte, zapytaj o dane z tabeli suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Jak widać wartość w group_id
kolumna XYZ Corp
w tabeli suppliers
zmieniono z 1 na 100, gdy zaktualizowaliśmy group_id
w suplier_groups
stół. To jest wynik ON UPDATE CASCADE
działanie.
Po szóste, usuń identyfikator grupy dostawców 2 z supplier_groups
tabela:
DELETE FROM supplier_groups
WHERE group_id = 2;
Code language: SQL (Structured Query Language) (sql)
Po siódme, zapytaj o dane z tabeli suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Identyfikator dostawcy 2, którego group_id
is 2 zostało usunięte, gdy identyfikator grupy dostawców 2 został usunięty z supplier_groups
stół. Jest to efekt ON DELETE CASCADE
działanie.
W tym samouczku dowiedziałeś się o ograniczeniach kluczy obcych SQLite i jak ich używać do wymuszania relacji między powiązanymi tabelami.