Tóm tắt :trong hướng dẫn này, bạn sẽ học cách sử dụng ràng buộc khóa ngoại SQLite để thực thi mối quan hệ giữa các bảng có liên quan.
Hỗ trợ ràng buộc khóa ngoại SQLite
SQLite đã hỗ trợ ràng buộc khóa ngoại kể từ phiên bản 3.6.19. Thư viện SQLite cũng phải được biên dịch bằng SQLITE_OMIT_FOREIGN_KEY và SQLITE_OMIT_TRIGGER.
Để kiểm tra xem phiên bản SQLite hiện tại của bạn có hỗ trợ các ràng buộc khóa ngoại hay không, bạn sử dụng lệnh sau.
PRAGMA foreign_keys;
Code language: SQL (Structured Query Language) (sql)
Lệnh trả về một giá trị số nguyên:1:enable, 0:disable. Nếu lệnh không trả về kết quả nào, điều đó có nghĩa là phiên bản SQLite của bạn không hỗ trợ các ràng buộc khóa ngoại.
Nếu thư viện SQLite được biên dịch với hỗ trợ ràng buộc khóa ngoại, ứng dụng có thể sử dụng PRAGMA foreign_keys
lệnh để bật hoặc tắt các ràng buộc khóa ngoại trong thời gian chạy.
Để tắt ràng buộc khóa ngoại:
PRAGMA foreign_keys = OFF;
Code language: SQL (Structured Query Language) (sql)
Để bật ràng buộc khóa ngoại:
PRAGMA foreign_keys = ON;
Code language: SQL (Structured Query Language) (sql)
Giới thiệu về các ràng buộc khóa ngoài SQLite
Hãy bắt đầu với hai bảng:suppliers
và 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)
Giả sử rằng mỗi nhà cung cấp thuộc một và chỉ một nhóm nhà cung cấp. Và mỗi nhóm nhà cung cấp có thể có 0 hoặc nhiều nhà cung cấp. Mối quan hệ giữa supplier_groups
và suppliers
bảng là một-nhiều. Nói cách khác, đối với mỗi hàng trong suppliers
, có một hàng tương ứng trong supplier_groups
bảng.
Hiện tại, không có cách nào ngăn bạn thêm hàng vào suppliers
bảng không có hàng tương ứng trong supplier_groups
bảng.
Ngoài ra, bạn có thể xóa một hàng trong supplier_groups
bảng mà không xóa hoặc cập nhật các hàng tương ứng trong suppliers
bàn. Điều này có thể để lại các hàng không có trong suppliers
bảng.
Để thực thi mối quan hệ giữa các hàng trong suppliers
và supplier_groups
bảng, bạn sử dụng ràng buộc khóa ngoại .
Để thêm ràng buộc khóa ngoại vào suppliers
, bạn thay đổi định nghĩa của CREATE TABLE
tuyên bố ở trên như sau:
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
bảng được gọi là bảng mẹ , là bảng mà khóa ngoại tham chiếu. Các nhà cung cấp suppliers
bảng được gọi là bảng con , là bảng áp dụng ràng buộc khóa ngoại.
group_id
trong supplier_groups
bảng được gọi là khóa cha , là một cột hoặc một tập hợp các cột trong bảng mẹ mà ràng buộc khóa ngoại tham chiếu. Thông thường, khóa cha là khóa chính của bảng cha.
group_id
trong suppliers
bảng được gọi là khóa con. Nói chung, khóa con tham chiếu đến khóa chính của bảng mẹ.
Ví dụ về ràng buộc khóa ngoài SQLite
Đầu tiên, hãy chèn ba hàng vào supplier_groups
bảng.
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
Thứ hai, chèn một nhà cung cấp mới vào suppliers
bảng với nhóm nhà cung cấp tồn tại trong supplier_groups
bảng.
INSERT INTO suppliers (supplier_name, group_id)
VALUES ('HP', 2);
Code language: SQL (Structured Query Language) (sql)
Câu lệnh này hoạt động hoàn toàn tốt.
Thứ ba, cố gắng chèn một nhà cung cấp mới vào suppliers
bảng có nhóm nhà cung cấp không tồn tại trong supplier_groups
bảng.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('ABC Inc.', 4);
Code language: SQL (Structured Query Language) (sql)
SQLite đã kiểm tra ràng buộc khóa ngoại, từ chối thay đổi và đưa ra thông báo lỗi sau:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
Hành động ràng buộc khóa ngoài SQLite
Điều gì sẽ xảy ra nếu bạn xóa một hàng trong supplier_groups
bàn? Nên tất cả các hàng tương ứng trong suppliers
bảng cũng bị xóa? Các câu hỏi tương tự đối với hoạt động cập nhật.
Để chỉ định cách hoạt động của ràng buộc khóa ngoại bất cứ khi nào khóa mẹ bị xóa hoặc cập nhật, bạn sử dụng ON DELETE
hoặc ON UPDATE
hành động như sau:
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 hỗ trợ các hành động sau:
- ĐẶT ĐẦY ĐỦ
- ĐẶT ĐỊNH NGHĨA
- HẠN CHẾ
- KHÔNG CÓ HÀNH ĐỘNG
- CASCADE
Trong thực tế, các giá trị của khóa chính trong bảng cha không thay đổi do đó các quy tắc cập nhật ít quan trọng hơn. Quy tắc quan trọng hơn là DELETE
quy tắc chỉ định hành động khi khóa mẹ bị xóa.
Chúng tôi sẽ xem xét từng hành động bằng ví dụ sau
ĐẶT ĐẦY ĐỦ
Khi khóa cha thay đổi, xóa hoặc cập nhật, các khóa con tương ứng của tất cả các hàng trong bảng con được đặt thành NULL.
Đầu tiên, thả và tạo bảng suppliers
sử dụng SET NULL
hành động cho group_id
khóa ngoại:
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)
Thứ hai, chèn một số hàng vào suppliers
bảng:
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)
Thứ ba, xóa id nhóm nhà cung cấp 3 khỏi supplier_groups
bảng:
DELETE FROM supplier_groups
WHERE group_id = 3;
Code language: SQL (Structured Query Language) (sql)
Thứ tư, truy vấn dữ liệu từ suppliers
bảng.
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Các giá trị của group_id
cột của các hàng tương ứng trong suppliers
bảng được đặt thành NULL.
ĐẶT ĐỊNH NGHĨA
SET DEFAULT
hành động đặt giá trị của khóa ngoại thành giá trị mặc định được chỉ định trong định nghĩa cột khi bạn tạo bảng.
Bởi vì các giá trị trong cột group_id
mặc định là NULL, nếu bạn xóa một hàng khỏi supplier_groups
bảng, các giá trị của group_id
sẽ được đặt thành NULL.
Sau khi ấn định giá trị mặc định, ràng buộc khóa ngoại bắt đầu hoạt động và thực hiện kiểm tra.
HẠN CHẾ
RESTRICT
hành động không cho phép bạn thay đổi hoặc xóa các giá trị trong khóa chính của bảng mẹ.
Đầu tiên, thả và tạo suppliers
bảng với RESTRICT
hành động trong khóa ngoại 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)
Thứ hai, chèn một hàng vào bảng suppliers
với group_id 1.
INSERT INTO suppliers (supplier_name, group_id)
VALUES('XYZ Corp', 1);
Code language: SQL (Structured Query Language) (sql)
Thứ ba, xóa nhóm nhà cung cấp có id 1 khỏi supplier_groups
bảng:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
SQLite đã phát hành lỗi sau:
[SQLITE_CONSTRAINT] Abort due to constraint violation (FOREIGN KEY constraint failed)
Code language: CSS (css)
Để khắc phục, trước tiên bạn phải xóa tất cả các hàng khỏi suppliers
bảng có group_id
1:
DELETE FROM suppliers
WHERE group_id =1;
Code language: SQL (Structured Query Language) (sql)
Sau đó, bạn có thể xóa nhóm nhà cung cấp 1 khỏi supplier_groups
bảng:
DELETE FROM supplier_groups
WHERE group_id = 1;
Code language: SQL (Structured Query Language) (sql)
KHÔNG HÀNH ĐỘNG
NO ACTION
không có nghĩa là bỏ qua ràng buộc khóa ngoại. Nó có tác dụng tương tự như RESTRICT
.
CASCADE
CASCADE
hành động truyền các thay đổi từ bảng mẹ sang bảng con khi bạn cập nhật hoặc xóa khóa mẹ.
Đầu tiên, hãy chèn suppliers
nhóm vào supplier_groups
bảng:
INSERT INTO supplier_groups (group_name)
VALUES
('Domestic'),
('Global'),
('One-Time');
Code language: SQL (Structured Query Language) (sql)
Thứ hai, thả và tạo bảng suppliers
với CASCADE
hành động trong khóa ngoại 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)
Thứ ba, chèn một số nhà cung cấp vào bảng 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)
Thứ tư, cập nhật group_id
của Domestic
nhóm nhà cung cấp đến 100:
UPDATE supplier_groups
SET group_id = 100
WHERE group_name = 'Domestic';
Code language: SQL (Structured Query Language) (sql)
Thứ năm, truy vấn dữ liệu từ bảng suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Như bạn có thể thấy giá trị trong group_id
của XYZ Corp
trong bảng suppliers
đã thay đổi từ 1 thành 100 khi chúng tôi cập nhật group_id
trong suplier_groups
bàn. Đây là kết quả của ON UPDATE CASCADE
hành động.
Thứ sáu, xóa id nhóm nhà cung cấp 2 khỏi supplier_groups
bảng:
DELETE FROM supplier_groups
WHERE group_id = 2;
Code language: SQL (Structured Query Language) (sql)
Thứ bảy, truy vấn dữ liệu từ bảng suppliers
:
SELECT * FROM suppliers;
Code language: SQL (Structured Query Language) (sql)
Id nhà cung cấp 2 có group_id
là 2 đã bị xóa khi id nhóm nhà cung cấp 2 bị xóa khỏi supplier_groups
bàn. Đây là hiệu ứng của ON DELETE CASCADE
hành động.
Trong hướng dẫn này, bạn đã học về ràng buộc khóa ngoại SQLite và cách sử dụng chúng để thực thi mối quan hệ giữa các bảng có liên quan.