Как создать тип ENUM в SQLite?

105

Мне нужно преобразовать таблицу из MySQL в SQLite, но я не могу понять, как преобразовать поле перечисления, потому что я не могу найти ENUMтип в SQLite.

Вышеупомянутое поле находится pTypeв следующей таблице:

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

Мне нужно поле только с тремя значениями для выбора пользователем, и я хотел бы применить это в БД, а не только в моем приложении.

onedevteam.com
источник

Ответы:

81

В SQLite нет типа enum, только следующее:

  • НОЛЬ
  • ЦЕЛОЕ
  • НАСТОЯЩИЙ
  • ТЕКСТ
  • BLOB

Источник: http://www.sqlite.org/datatype3.html

Я боюсь, что в вашем случае потребуется небольшая настраиваемая таблица перечисления.

MPelletier
источник
26
На самом деле «настраиваемая таблица перечислений» - это гораздо более
понятный
19
Почему бы не использовать ограничение CHECK (), чтобы разрешить только три возможных строки?
mateusza
1
@Wideshanks, я не думаю, что CHECK()существовал в то время, когда я писал этот ответ. Если строка не является действительно коротким, я категорически против этого. Максимум 1 или 2 символа.
MPelletier
Я могу использовать VARCHARв своей версии SQLite, это добавление нового типа?
Hamman Samuel
3
@HammanSamuel Это не новость, это решено как значение TEXT. На исходной странице, которую я предоставил, см. Пункт 2.1 об определении родства столбцов.
MPelletier
106

Способ SQLite - использовать ограничение CHECK .

Некоторые примеры:

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

Это ограничит pTypeстолбец только значениями M, Rи H, как enum("M", "R", "H")и в некоторых других механизмах SQL.

Матеуша
источник
2
Welp, на самом деле эта реализация не полностью эмулируется, enumпотому что делает невозможным сортировку по целочисленному индексу значений (что возможно с фактическим enumполем). Просто имейте это в виду.
Борис Д. Теохаров
53

Чтобы расширить ответ MPelletier, вы можете создать такие таблицы:

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

Теперь значения перечисления доступны непосредственно в таблице цен, как если бы они использовали ENUM: вам не нужно присоединяться к таблице PriceType, чтобы получить значения Type, вам нужно использовать ее только в том случае, если вы хотите определить последовательность ENUM.

Ограничения внешнего ключа были введены в SQLite версии 3.6.19.

ChrisV
источник
3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Должна появиться синтаксическая ошибка. «Первая форма (с ключевым словом« VALUES ») создает одну новую строку в существующей таблице». : sqlite.org/lang_insert.html . Разбей, INSERT INTO PriceType(Type, Seq) VALUES ('M',1); INSERT INTO PriceType(Type, Seq) VALUES ('R',2); INSERT INTO PriceType(Type, Seq) VALUES ('H',3);
избегай
9
Не забывайте делать это PRAGMA foreign_keys = ON;для каждой сессии - потому что fkeys по умолчанию отключены в
sqlite3
3
Если вы не хотите забывать, PRAGMA foreign_keys = ON;вы можете настроить это в своем файле .sqliterc в своем домашнем каталоге.
Eradicatore
1
Кроме того, вы можете использовать UNIQUEограничение на Seq. Примерно такCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore
1
Зачем вам создавать отдельный столбец Seq вместо того, чтобы просто использовать столбец rowid по умолчанию ?
Парфянский выстрел