Cách tạo kiểu ENUM trong SQLite?


104

Tôi cần chuyển đổi một bảng từ MySQL sang SQLite, nhưng tôi không thể tìm ra cách chuyển đổi trường enum, vì tôi không thể tìm thấy ENUMkiểu trong SQLite.

Trường nói trên nằm pTypetrong bảng sau:

CREATE TABLE `prices` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `pName` VARCHAR(100) NOT NULL DEFAULT '',
    `pType` ENUM('M','R','H') NOT NULL DEFAULT 'M',
    `pField` VARCHAR(50) NULL DEFAULT NULL,
    `pFieldExt` VARCHAR(50) NULL DEFAULT NULL,
    `cmp_id` INT(11) NOT NULL DEFAULT '0',
    PRIMARY KEY (`id`)
)
ENGINE=MyISAM
ROW_FORMAT=DEFAULT

Tôi cần một trường chỉ có ba giá trị để người dùng chọn và tôi muốn thực thi điều đó trong DB, không chỉ trong ứng dụng của tôi.

Câu trả lời:


81

Không có kiểu enum trong SQLite, chỉ có kiểu sau:

  • VÔ GIÁ TRỊ
  • INTEGER
  • THỰC TẾ
  • BẢN VĂN
  • BÃI

Nguồn: http://www.sqlite.org/datatype3.html

Tôi e rằng một bảng enum nhỏ, tùy chỉnh sẽ được yêu cầu trong trường hợp của bạn.


26
Trên thực tế "một bảng tùy chỉnh enum" là một trình dọn dẹp thiết kế nhiều mà sử dụng enums thực
a_horse_with_no_name

19
Tại sao không sử dụng ràng buộc CHECK () để chỉ cho phép ba chuỗi có thể?
mateusza

1
@ Cảm ơn Tôi không nghĩ rằng CHECK()đã tồn tại vào thời điểm tôi viết câu trả lời đó. Trừ khi chuỗi thực sự ngắn, tôi hoàn toàn phản đối. Tối đa 1 hoặc 2 ký tự.
MPelletier

Tôi có thể sử dụng VARCHARtrong phiên bản SQLite của mình, đó có phải là kiểu bổ sung mới không?
Hamman Samuel

3
@HammanSamuel Nó không phải là mới, nó được giải quyết theo ý nghĩa TEXT. Trên trang nguồn mà tôi đã cung cấp, hãy xem điểm 2.1 về Xác định mối quan hệ của cột.
MPelletier

105

Cách SQLite là sử dụng ràng buộc CHECK .

Vài ví dụ:

CREATE TABLE prices (
 id         INTEGER                                PRIMARY KEY,
 pName      TEXT CHECK( LENGTH(pName) <= 100 )     NOT NULL DEFAULT '',
 pType      TEXT CHECK( pType IN ('M','R','H') )   NOT NULL DEFAULT 'M',
 pField     TEXT CHECK( LENGTH(pField) <= 50 )     NULL DEFAULT NULL,
 pFieldExt  TEXT CHECK( LENGTH(pFieldExt) <= 50 )  NULL DEFAULT NULL,
 cmp_id     INTEGER                                NOT NULL DEFAULT '0'
)

Điều này sẽ hạn chế pTypecột để chỉ các giá trị M, RH, giống như enum("M", "R", "H")sẽ làm ở một số công cụ SQL khác.


2
Welp, thực sự việc triển khai này không mô phỏng hoàn toàn enumvì nó khiến nó không thể sắp xếp theo chỉ số nguyên của các giá trị (điều này có thể xảy ra với một enumtrường thực tế ). Chỉ là, mọi người, hãy ghi nhớ điều đó.
Boris D. Teoharov

53

Để mở rộng câu trả lời của MPelletier, bạn có thể tạo các bảng như sau:

CREATE TABLE Price (
  PriceId INTEGER       PRIMARY KEY AUTOINCREMENT NOT NULL,
  Name    VARCHAR(100)  NOT NULL,
  Type    CHAR(1)       NOT NULL DEFAULT ('M') REFERENCES PriceType(Type)
);

CREATE TABLE PriceType (
  Type    CHAR(1)       PRIMARY KEY NOT NULL,
  Seq     INTEGER
);
INSERT INTO PriceType(Type, Seq) VALUES ('M',1);
INSERT INTO PriceType(Type, Seq) VALUES ('R',2);
INSERT INTO PriceType(Type, Seq) VALUES ('H',3);

Bây giờ các giá trị kiểu liệt kê có sẵn trực tiếp trong bảng Giá như chúng sẽ được sử dụng ENUM: bạn không cần tham gia vào bảng PriceType để nhận các giá trị Loại, bạn chỉ cần sử dụng nó nếu bạn muốn xác định chuỗi của ENUM.

Các ràng buộc khóa ngoại được giới thiệu trong phiên bản SQLite 3.6.19.


3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Bạn sẽ gặp lỗi cú pháp. "Biểu mẫu đầu tiên (với từ khóa" VALUES ") tạo một hàng mới trong bảng hiện có." : sqlite.org/lang_insert.html . Phá vỡ nó lên tránh rằng:INSERT INTO PriceType(Type, Seq) VALUES ('M',1); INSERT INTO PriceType(Type, Seq) VALUES ('R',2); INSERT INTO PriceType(Type, Seq) VALUES ('H',3);
ahcox

9
Đừng quên PRAGMA foreign_keys = ON;cho mỗi phiên làm việc - vì fkeys được tắt theo mặc định trong sqlite3
smathy

3
Nếu bạn muốn tránh quên PRAGMA foreign_keys = ON;thì bạn có thể thiết lập nó trong tệp .sqliterc trong thư mục chính của bạn.
Eradicatore

1
Ngoài ra, bạn có thể muốn sử dụng UNIQUEràng buộc trên Seq. Một cái gì đó như thế nàyCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore

1
Tại sao bạn lại tạo một cột 'Seq' riêng biệt thay vì chỉ sử dụng cột rowid mặc định ?
Parthian Shot,
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.