Oversigt :i dette selvstudie lærer du, hvordan du bruger SQLite-fremmednøglebegrænsningen til at håndhæve relationerne mellem relaterede tabeller.
SQLite-understøttelse af fremmednøglebegrænsning
SQLite har understøttet begrænsning af fremmednøgle siden version 3.6.19. SQLite-biblioteket skal heller ikke være kompileret med hverken SQLITE_OMIT_FOREIGN_KEY eller SQLITE_OMIT_TRIGGER.
For at kontrollere, om din nuværende version af SQLite understøtter fremmednøglebegrænsninger eller ej, skal du bruge følgende kommando.
PRAGMA foreign_keys;
Code language: SQL (Structured Query Language) (sql)
Kommandoen returnerer en heltalsværdi:1:aktiveret, 0:deaktiveret. Hvis kommandoen ikke returnerer noget, betyder det, at din SQLite-version ikke understøtter fremmednøglebegrænsninger.
Hvis SQLite-biblioteket er kompileret med understøttelse af fremmednøglebegrænsninger, kan applikationen bruge PRAGMA foreign_keys
kommando for at aktivere eller deaktivere fremmednøglebegrænsninger under kørsel.
Sådan deaktiveres begrænsning af fremmednøgle:
PRAGMA foreign_keys = OFF;
Code language: SQL (Structured Query Language) (sql)
Sådan aktiverer du begrænsning af fremmednøgle:
PRAGMA foreign_keys = ON;
Code language: SQL (Structured Query Language) (sql)
Introduktion til SQLites fremmednøglebegrænsninger
Lad os starte med to tabeller:suppliers
og 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)
Forudsat at hver leverandør tilhører én og kun én leverandørgruppe. Og hver leverandørgruppe kan have nul eller mange leverandører. Forholdet mellem supplier_groups
og suppliers
borde er en-til-mange. Med andre ord, for hver række i suppliers
tabel, er der en tilsvarende række i supplier_groups
tabel.
I øjeblikket er der ingen måde at forhindre dig i at tilføje en række til suppliers
tabel uden en tilsvarende række i supplier_groups
tabel.
Derudover kan du fjerne en række i supplier_groups
tabel uden at slette eller opdatere de tilsvarende rækker i suppliers
bord. Dette kan efterlade forældreløse rækker i suppliers
tabel.
For at håndhæve forholdet mellem rækker i suppliers
og supplier_groups
tabel, bruger du fremmednøglebegrænsningerne .
For at tilføje den fremmede nøgle begrænsning til suppliers
tabel, ændrer du definitionen af CREATE TABLE
erklæring ovenfor som følger:
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
tabel kaldes en overordnet tabel , som er den tabel, som en fremmednøgle refererer til. suppliers
tabel er kendt som en underordnet tabel , som er den tabel, som den fremmede nøgle-begrænsning gælder for.
group_id
kolonne i supplier_groups
tabellen kaldes overordnet nøgle , som er en kolonne eller et sæt af kolonner i den overordnede tabel, som den fremmede nøgle-begrænsning refererer til. Typisk er den overordnede nøgle den primære nøgle i den overordnede tabel.
group_id
kolonnen i suppliers
tabel kaldes den underordnede nøgle. Generelt refererer den underordnede nøgle til den primære nøgle i den overordnede tabel.
Eksempel på SQLite-fremmednøglebegrænsning
Indsæt først tre rækker i supplier_groups
tabel.
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
For det andet skal du indsætte en ny leverandør i suppliers
tabel med leverandørgruppen, der findes i supplier_groups
tabel.
INSERT INTO suppliers (supplier_name, group_id)
VALUES ('HP', 2);
Code language: SQL (Structured Query Language) (sql)
Denne erklæring fungerer helt fint.
For det tredje, forsøg at indsætte en ny leverandør i suppliers
tabel med leverandørgruppen, der ikke findes i supplier_groups
tabel.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('ABC Inc.', 4);
Code language: SQL (Structured Query Language) (sql)
SQLite kontrollerede den fremmede nøgle-begrænsning, afviste ændringen og udsendte følgende fejlmeddelelse:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
SQLite-fremmednøglehandlinger
Hvad ville der ske, hvis du sletter en række i supplier_groups
bord? Skal alle de tilsvarende rækker i suppliers
tabel er også slettet? De samme spørgsmål til opdateringsoperationen.
For at angive, hvordan en fremmednøgle-begrænsning opfører sig, når den overordnede nøgle slettes eller opdateres, bruger du ON DELETE
eller ON UPDATE
handling som følger:
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 understøtter følgende handlinger:
- INDSTILL NULL
- INDSTILL STANDARD
- BEGRÆNS
- INGEN HANDLING
- CASCADE
I praksis ændres værdierne af den primære nøgle i den overordnede tabel ikke, derfor er opdateringsreglerne mindre vigtige. Den vigtigere regel er DELETE
regel, der angiver handlingen, når den overordnede nøgle slettes.
Vi vil undersøge hver handling ved hjælp af følgende eksempel
INDSTIL NULL
Når den overordnede nøgle ændres, slettes eller opdateres, indstilles de tilsvarende undernøgler i alle rækker i den underordnede tabel til NULL.
Først skal du slippe og oprette tabellen suppliers
ved at bruge SET NULL
handling for group_id
fremmednøgle:
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)
For det andet, indsæt nogle rækker i suppliers
tabel:
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)
For det tredje skal du slette leverandørgruppe-id 3 fra supplier_groups
tabel:
DELETE FROM supplier_groups
WHERE group_id = 3;
Code language: SQL (Structured Query Language) (sql)
For det fjerde, forespørg data fra suppliers
tabel.
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Værdierne for group_id
kolonne i de tilsvarende rækker i suppliers
tabel sat til NULL.
INDSTILL STANDARD
SET DEFAULT
action indstiller værdien af fremmednøglen til standardværdien angivet i kolonnedefinitionen, når du opretter tabellen.
Fordi værdierne i kolonnen group_id
standard til NULL, hvis du sletter en række fra supplier_groups
tabel, værdierne af group_id
indstilles til NULL.
Efter at have tildelt standardværdien, træder den fremmede nøgle-begrænsning ind og bærer kontrollen.
BEGRÆNS
RESTRICT
handling tillader dig ikke at ændre eller slette værdier i den overordnede nøgle til den overordnede tabel.
Slip først og opret suppliers
tabel med RESTRICT
handling i fremmednøglen 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)
For det andet skal du indsætte en række i tabellen suppliers
med group_id 1.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('XYZ Corp', 1);
Code language: SQL (Structured Query Language) (sql)
For det tredje skal du slette leverandørgruppen med id 1 fra supplier_groups
tabel:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
SQLite udsendte følgende fejl:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
For at rette det, skal du først slette alle rækker fra suppliers
tabel, som har group_id
1:
DELETE FROM suppliers
WHERE group_id =1;
Code language: SQL (Structured Query Language) (sql)
Derefter kan du slette leverandørgruppe 1 fra supplier_groups
tabel:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
INGEN HANDLING
NO ACTION
betyder ikke omgå begrænsningen af den fremmede nøgle. Det har samme effekt som RESTRICT
.
CASCADE
CASCADE
handling overfører ændringerne fra den overordnede tabel til den underordnede tabel, når du opdaterer eller sletter den overordnede nøgle.
Indsæt først supplier
grupper i supplier_groups
tabel:
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
For det andet skal du slippe og oprette tabellen suppliers
med CASCADE
handling i fremmednøglen 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)
For det tredje, indsæt nogle leverandører i tabellen 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)
For det fjerde skal du opdatere group_id
af Domestic
leverandørgruppe til 100:
UPDATE supplier_groups
SET group_id = 100
WHERE group_name = 'Domestic';
Code language: SQL (Structured Query Language) (sql)
For det femte, forespørg data fra tabellen suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Som du kan se værdien i group_id
kolonne i XYZ Corp
i tabellen suppliers
ændret fra 1 til 100, da vi opdaterede group_id
i suplier_groups
bord. Dette er resultatet af ON UPDATE CASCADE
handling.
For det sjette, slet leverandørgruppe-id 2 fra supplier_groups
tabel:
DELETE FROM supplier_groups
WHERE group_id = 2;
Code language: SQL (Structured Query Language) (sql)
For det syvende, forespørg data fra tabellen suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Leverandør-id 2, hvis group_id
is 2 blev slettet, da leverandørgruppe-id 2 blev fjernet fra supplier_groups
bord. Dette er effekten af ON DELETE CASCADE
handling.
I dette selvstudie har du lært om SQLite-fremmednøglebegrænsninger, og hvordan du bruger dem til at håndhæve forholdet mellem relaterede tabeller.