SQLite
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> SQLite

Cách bỏ khóa ngoại trong SQLite

Thông thường, nếu bạn cần bỏ khóa ngoại trong SQL, bạn sẽ sử dụng ALTER TABLE tuyên bố. Nhưng nếu bạn đang sử dụng SQLite, đó không phải là một tùy chọn.

SQLite hỗ trợ một tập con rất hạn chế của ALTER TABLE tuyên bố. Những điều duy nhất bạn có thể làm với ALTER TABLE trong SQLite là đổi tên bảng, đổi tên cột trong bảng hoặc thêm cột mới vào bảng hiện có.

Nói cách khác, bạn không thể sử dụng ALTER TABLE để thả một khóa ngoại như bạn có thể làm trong các RDBMS khác

Cách được khuyến nghị để “bỏ” khóa ngoại trong SQLite thực sự là chuyển dữ liệu sang một bảng mới mà không có khóa ngoại (hoặc với một bảng khác, nếu đó là thứ bạn cần).

Cách được Đề xuất

Tài liệu SQLite đề xuất quy trình 12 bước để thực hiện các thay đổi giản đồ đối với bảng. Chúng tôi sẽ sử dụng quy trình đó để "thả" khóa ngoại trong ví dụ sau.

Tạo bảng bằng khóa ngoại

Đầu tiên, hãy tạo một bảng với khóa ngoại và điền dữ liệu vào bảng đó.

CREATE TABLE Types( 
    TypeId INTEGER PRIMARY KEY, 
    Type
);

CREATE TABLE Pets( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId,
    FOREIGN KEY(TypeId) REFERENCES Types(TypeId)
);

INSERT INTO Types VALUES 
    ( NULL, 'Dog' ),
    ( NULL, 'Cat' ),
    ( NULL, 'Parakeet' ),
    ( NULL, 'Hamster' );

INSERT INTO Pets VALUES 
    ( NULL, 'Brush', 3 ),
    ( NULL, 'Tweet', 3 ),
    ( NULL, 'Yelp', 1 ),
    ( NULL, 'Woofer', 1 ),
    ( NULL, 'Fluff', 2 );

Trên thực tế, ở đây tôi đã tạo hai bảng và điền dữ liệu vào chúng. Hai bảng, vì bảng đầu tiên ( Loại ) có khóa chính và khóa khác ( Thú cưng ) có khóa ngoại. Khóa ngoại đã được thêm vào dòng cuối cùng của bảng thứ hai.

Chúng tôi có thể xác minh rằng khóa ngoại đã được tạo bằng cách chạy lệnh sau:

PRAGMA foreign_key_list(Pets);

Kết quả:

 id  seq  table  from    to      on_update  on_delete  match
 --  ---  -----  ------  ------  ---------  ---------  -----
 0   0    Types  TypeId  TypeId  NO ACTION  NO ACTION  NONE  

Chúng ta có thể xem chi tiết về ràng buộc khóa ngoại.

Bây giờ chúng ta hãy "thả" khóa ngoại.

“Bỏ” Khoá ngoại

Đoạn mã sau "loại bỏ" khóa ngoại bằng cách tạo một bảng mới không có ràng buộc khóa ngoại, chuyển dữ liệu sang bảng đó, xóa bảng gốc, sau đó đổi tên bảng mới thành tên của bảng gốc.

PRAGMA foreign_keys = OFF;

BEGIN TRANSACTION;

CREATE TABLE Pets_new( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId
);

INSERT INTO Pets_new SELECT * FROM Pets;

DROP TABLE Pets;

ALTER TABLE Pets_new RENAME TO Pets;

COMMIT;

PRAGMA foreign_keys = ON;

Đã xong.

Nếu bạn cần tạo lại bất kỳ chỉ mục, trình kích hoạt hoặc chế độ xem nào, hãy thực hiện điều đó sau ALTER TABLE câu lệnh đổi tên bảng (ngay trước COMMIT ).

Bây giờ chúng ta hãy kiểm tra lại bảng xem có các ràng buộc khóa ngoại không.

PRAGMA foreign_key_list(Pets);

Kết quả:

 

(Ô trống vì không có ràng buộc khóa ngoại nào trên bảng này.)

Bạn có thể sử dụng cùng một phương pháp để thêm khóa ngoại vào bảng hiện có.

Một phương pháp thay thế

Khi xem ví dụ trước, bạn có thể nghĩ rằng có một cách hiệu quả hơn để làm điều đó. Ví dụ, bạn có thể làm như thế này:

PRAGMA foreign_keys = OFF;

BEGIN TRANSACTION;

ALTER TABLE Pets RENAME TO Pets_old;

CREATE TABLE Pets( 
    PetId INTEGER PRIMARY KEY, 
    PetName,
    TypeId
);

INSERT INTO Pets SELECT * FROM Pets_old;

DROP TABLE Pets_old;

COMMIT;

PRAGMA foreign_keys = ON;

Và đó là sự thật. Với ví dụ của tôi, phương pháp này cũng hoạt động.

Nhưng phương pháp này cũng có khả năng làm hỏng các tham chiếu đến bảng trong bất kỳ trình kích hoạt, chế độ xem và ràng buộc khóa ngoại hiện có nào.

Vì vậy, nếu bảng của bạn đã có các trình kích hoạt, chế độ xem hoặc các ràng buộc khóa ngoại hiện tại, thì có lẽ bạn nên sử dụng phương pháp được đề xuất sẽ an toàn hơn.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Truy xuất cơ sở dữ liệu hoặc bất kỳ tệp nào khác từ Bộ nhớ trong bằng run-as

  2. Lưu trữ cấu hình trong android

  3. Kiểm tra xem chuỗi cột trong cơ sở dữ liệu có phải là chuỗi con của một truy vấn trong sqlite không

  4. Không hài lòngLinkError trong phương pháp gốc

  5. Khóa ngoại SQLite