Як створити тип 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

Мені потрібно поле з лише трьома значеннями, які користувач обрав, і я хотів би застосувати це в БД, а не лише в моїй програмі.

Відповіді:


81

У SQLite немає enum типу, лише наступне:

  • НУЛЬ
  • ІНТЕГЕР
  • РЕАЛЬНА
  • ТЕКСТ
  • БЛОБ

Джерело: http://www.sqlite.org/datatype3.html

Боюся, у вашому випадку буде потрібна невелика спеціальна таблиця перерахунків.


26
Насправді "спеціальна таблиця перерахувань" - це набагато чистіший дизайн, який використовує справжні перерахунки
a_horse_with_no_name

19
Чому б не використовувати обмеження CHECK (), щоб дозволити лише три можливі рядки?
mateusza

1
@Wideshanks Я не думаю, що CHECK()існував під час написання цієї відповіді. Якщо струна не є дійсно короткою, я абсолютно проти. Максимум 1 або 2 символи.
MPelletier

Я можу використовувати VARCHARу своїй версії SQLite, це нове доповнення типу?
Хамман Самуель

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, щоб отримати значення типу, використовувати його потрібно лише у тому випадку, якщо ви хочете визначити послідовність ENUMs.

Зовнішні ключові обмеження були введені у версії 3.6.19 SQLite.


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

9
Не забувайте PRAGMA foreign_keys = ON;про кожен сеанс - адже файли за замовчуванням відключені в sqlite3
smathy

3
Якщо ви хочете уникнути забуття, PRAGMA foreign_keys = ON;ви можете встановити це у вашому .sqliterc-файлі у вашому домашньому каталозі.
Ерадикатор

1
Крім того, ви можете використовувати UNIQUEобмеження на Seq. Щось подібнеCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore

1
Чому б ви створили окремий стовпчик "Послідовність" замість того, щоб просто використовувати стовпець із замовчуванням в рядку ?
Парфянський розстріл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.