Trong SQLite, bạn có thể thả một bảng với DROP TABLE
tuyên bố.
Bạn có thể tùy chọn thêm IF EXISTS
mệnh đề ngăn chặn bất kỳ lỗi nào có thể xảy ra nếu bảng không tồn tại.
Ngoài ra, nếu bảng được tham chiếu bằng khóa ngoại, có một số điều cần lưu ý.
Ví dụ
Dưới đây là một ví dụ để chứng minh cách đơn giản nhất để bỏ một bảng trong SQLite:
DROP TABLE t1;
Thao tác này sẽ làm giảm bảng có tên t1
.
Bạn có thể tùy ý thêm tiền tố tên bảng với tên lược đồ.
Sử dụng IF EXISTS
Mệnh đề
Bạn có thể sử dụng IF EXISTS
để loại bỏ bất kỳ lỗi nào có thể xảy ra trong trường hợp bảng không tồn tại.
DROP TABLE IF EXISTS t2;
Nếu chúng ta loại bỏ IF EXISTS
và chạy lại điều đó, chúng tôi gặp lỗi.
Ví dụ:
DROP TABLE t2;
Kết quả:
Error: no such table: t2
Khoá ngoại và Xem phụ thuộc
SQLite không hỗ trợ CASCADE
và RESTRICT
từ khóa, được bao gồm trong tiêu chuẩn SQL và được hỗ trợ bởi một số RDBMS khác (chẳng hạn như PostgreSQL). Những từ khóa này được thiết kế để chỉ định những việc cần làm khi bảng đích có các thành phần phụ thuộc (chẳng hạn như chế độ xem hoặc khóa ngoại tham chiếu đến bảng).
Do SQLite không hỗ trợ các từ khóa này, đây là cách SQLite xử lý các chế độ xem và khóa ngoại khi bạn cố gắng bỏ một bảng.
SQLite bỏ qua bất kỳ chế độ xem phụ thuộc nào. Nói cách khác, nó tiếp tục và làm rơi bảng, ngay cả khi có một chế độ xem tham chiếu đến nó.
Đối với khóa ngoại…
Đầu tiên, các khóa ngoại bị tắt theo mặc định trong SQLite. Vì vậy, trừ khi bạn kích hoạt chúng, bất kỳ khóa ngoại nào tham chiếu đến bảng mục tiêu sẽ không có tác động đến việc bỏ bảng mục tiêu. Nói cách khác, bảng sẽ bị loại bỏ.
Nếu khóa ngoại được bật trong phiên của bạn, thì chúng sẽ chỉ ngăn việc rớt bảng nếu có dữ liệu vi phạm khóa ngoại đó. Nếu bảng con của bạn không chứa dữ liệu, thì bảng mẹ sẽ bị loại bỏ mà không có lỗi. Nếu bảng con chứa dữ liệu (có thể bao gồm dữ liệu tham chiếu đến khóa chính của bảng mẹ) thì điều này sẽ dẫn đến lỗi và bảng sẽ không bị xóa.
Như thế này:
PRAGMA foreign_keys = ON;
DROP TABLE t1;
Kết quả:
Error: FOREIGN KEY constraint failed
Lý do nó hoạt động như vậy là do SQLite thực hiện DELETE FROM
ngầm định thao tác trước khi thả bàn. Nếu DELETE FROM
hoạt động dẫn đến vi phạm khóa ngoại, sau đó chúng tôi nhận được lỗi. Nhưng nếu không có dữ liệu nào trong bảng thì DELETE FROM
bất kỳ hoạt động sẽ không dẫn đến vi phạm khóa ngoại và bảng có thể bị loại bỏ.
Nói tóm lại, nó không phải là DROP TABLE
thao tác gây ra bất kỳ vi phạm khóa ngoại nào, đó là DELETE FROM
ngầm hiểu hoạt động.
Khi Khóa ngoại sử dụng ON DELETE CASCADE
Tuy nhiên, nếu ràng buộc khóa ngoại được xác định bằng ON DELETE CASCADE
thì bảng mẹ sẽ bị xóa và mọi hàng tham chiếu đến cột khóa chính của bảng đó sẽ bị xóa trong bảng con.
Đây là một ví dụ.
Tạo bảng và chèn dữ liệu:
CREATE TABLE t11 (
c1 integer PRIMARY KEY AUTOINCREMENT
);
CREATE TABLE t12 (
c1 integer PRIMARY KEY AUTOINCREMENT,
c2 integer REFERENCES t11 (c1) ON DELETE CASCADE
);
INSERT INTO t11 VALUES (1);
INSERT INTO t12 VALUES (1, 1);
Chọn dữ liệu:
sqlite> SELECT * FROM t11;
c1
--
1
sqlite> SELECT * FROM t12;
c1 c2
-- --
1 1
Bỏ bảng mẹ và xem lại tất cả các bảng:
sqlite> DROP TABLE t11;
sqlite> .tables
t12
Chúng ta có thể thấy rằng t11
không còn tồn tại, nhưng t12
vẫn tồn tại.
Kiểm tra khóa ngoại trên t12
:
sqlite> PRAGMA foreign_key_list(t12);
id seq table from to on_update on_delete match
-- --- ----- ---- -- --------- --------- -----
0 0 t11 c2 c1 NO ACTION CASCADE NONE
Có, điều đó vẫn tồn tại và chúng tôi có thể xác nhận rằng nó có ON DELETE CASCADE
.
Chọn dữ liệu từ t12
:
sqlite> SELECT * FROM t12;
sqlite>
Không có hàng nào được trả lại. Điều này là do ON DELETE CASCADE
tùy chọn trên khóa ngoại đảm bảo rằng hàng đã bị xóa khi bảng mẹ (t11
) đã bị loại bỏ (hay chính xác hơn, khi dữ liệu của nó bị xóa thông qua DELETE FROM
ngầm hiểu hoạt động trước khi bị bỏ).
Đánh rơi khóa ngoại
SQLite không thực sự hỗ trợ bỏ khóa ngoại. Thông thường trong SQL, bạn bỏ khóa ngoại bằng ALTER TABLE
nhưng ALTER TABLE
của SQLite triển khai không cho phép loại bỏ các ràng buộc.
Tuy nhiên, có một cách để đối phó với tình huống này. Xem Cách bỏ khóa ngoại trong SQLite để làm ví dụ.