Bagaimana cara membuat tipe ENUM di SQLite?

105

Saya perlu mengonversi tabel dari MySQL ke SQLite, tetapi saya tidak tahu cara mengonversi kolom enum, karena saya tidak dapat menemukan ENUMjenis di SQLite.

Bidang yang disebutkan di atas ada pTypedi tabel berikut:

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

Saya memerlukan kolom dengan hanya tiga nilai untuk dipilih pengguna, dan saya ingin menerapkannya di DB, tidak hanya di aplikasi saya.

onedevteam.com
sumber

Jawaban:

81

Tidak ada jenis enum di SQLite, hanya berikut ini:

  • BATAL
  • BILANGAN BULAT
  • NYATA
  • TEKS
  • GUMPAL

Sumber: http://www.sqlite.org/datatype3.html

Saya khawatir tabel enum kecil khusus akan diperlukan dalam kasus Anda.

MPelletier
sumber
26
Sebenarnya "tabel enum khusus" adalah desain yang jauh lebih
rapi
19
Mengapa tidak menggunakan batasan CHECK () untuk mengizinkan hanya tiga kemungkinan string?
mateusza
1
@Wideshanks Saya rasa tidak CHECK()ada saat saya menulis jawaban itu. Kecuali jika talinya sangat pendek, saya benar-benar menentangnya. Maksimal 1 atau 2 karakter.
MPelletier
Saya dapat menggunakan VARCHARversi SQLite saya, apakah itu tambahan tipe baru?
Hamman Samuel
3
@HammanSamuel Ini bukan hal baru, itu diselesaikan sebagai makna TEXT. Pada halaman sumber yang saya berikan, lihat poin 2.1 tentang Penentuan Afinitas Kolom.
MPelletier
106

Cara SQLite adalah dengan menggunakan kendala PERIKSA .

Beberapa contoh:

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'
)

Hal ini akan membatasi pTypekolom hanya nilai-nilai M, Rdan H, seperti enum("M", "R", "H")yang akan dilakukan di beberapa mesin SQL lainnya.

mateusza
sumber
2
Yah, sebenarnya implementasi ini tidak sepenuhnya meniru enumkarena tidak memungkinkan untuk mengurutkan berdasarkan indeks integer dari nilai-nilai (yang dimungkinkan dengan enumbidang sebenarnya ). Hanya, semuanya, ingatlah itu.
Boris D. Teoharov
53

Untuk memperluas jawaban MPelletier, Anda dapat membuat tabel seperti ini:

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);

Sekarang nilai enumerasi tersedia langsung di tabel Price karena akan menggunakan ENUM: Anda tidak perlu bergabung dengan tabel PriceType untuk mendapatkan nilai Type, Anda hanya perlu menggunakannya jika Anda ingin menentukan urutan dari ENUM.

Batasan kunci asing diperkenalkan di SQLite versi 3.6.19.

ChrisV
sumber
3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Anda akan mendapatkan kesalahan sintaks. "Formulir pertama (dengan kata kunci" VALUES ") membuat satu baris baru dalam tabel yang ada." : sqlite.org/lang_insert.html . Putus hindari: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
Jangan lupa PRAGMA foreign_keys = ON;untuk setiap sesi - karena fkeys dinonaktifkan secara default di sqlite3
smathy
3
Jika Anda ingin menghindari lupa PRAGMA foreign_keys = ON;maka Anda dapat mengaturnya di file .sqliterc Anda di direktori home Anda.
Eradicatore
1
Juga, Anda mungkin ingin menggunakan UNIQUEbatasan pada Seq. Sesuatu seperti iniCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore
1
Mengapa Anda membuat kolom 'Seq' terpisah daripada hanya menggunakan kolom rowid default ?
Parthian Shot