Jak stworzyć typ ENUM w SQLite?

105

Muszę przekonwertować tabelę z MySQL na SQLite, ale nie mogę dowiedzieć się, jak przekonwertować pole wyliczenia, ponieważ nie mogę znaleźć ENUMtypu w SQLite.

Wspomniane pole znajduje się pTypew poniższej tabeli:

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

Potrzebuję pola zawierającego tylko trzy wartości do wyboru przez użytkownika i chciałbym wymusić to w bazie danych, a nie tylko w mojej aplikacji.

onedevteam.com
źródło

Odpowiedzi:

81

W SQLite nie ma typu wyliczenia, tylko następujące:

  • ZERO
  • LICZBA CAŁKOWITA
  • REAL
  • TEKST
  • KROPELKA

Źródło: http://www.sqlite.org/datatype3.html

Obawiam się, że w Twoim przypadku będzie wymagana mała, niestandardowa tabela wyliczeń.

MPelletier
źródło
26
Właściwie „niestandardowa tabela
wyliczeń
19
Dlaczego nie użyć ograniczenia CHECK (), aby zezwolić tylko na trzy możliwe ciągi?
mateusza
1
@Wideshanks, wydaje mi się, że nie CHECK()istniał w momencie, gdy pisałem tę odpowiedź. Jeśli struna nie jest naprawdę krótka, jestem temu całkowicie przeciwny. Maksymalnie 1 lub 2 znaki.
MPelletier
Mogę używać VARCHARw mojej wersji SQLite, czy to jest nowy dodatek typu?
Hamman Samuel
3
@HammanSamuel To nie jest nowe, zostało rozwiązane jako znaczenie TEXT. Na stronie źródłowej, którą podałem, patrz punkt 2.1 na temat określania powinowactwa kolumn.
MPelletier,
106

Sposób SQLite polega na użyciu ograniczenia CHECK .

Kilka przykładów:

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

Pozwoli to ograniczyć pTypekolumnę tylko wartości M, Roraz H, podobnie jak enum("M", "R", "H")byłoby zrobić w niektórych innych silników SQL.

mateusza
źródło
2
W rzeczywistości ta implementacja nie emuluje w pełni, enumponieważ uniemożliwia sortowanie według indeksów całkowitych wartości (co jest możliwe w przypadku rzeczywistego enumpola). Po prostu wszyscy, miejcie to na uwadze.
Boris D. Teoharov
53

Aby rozwinąć odpowiedź MPelletier, możesz utworzyć takie tabele:

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

Teraz wartości wyliczenia są dostępne bezpośrednio w tabeli Price, tak jak przy użyciu ENUM: nie musisz łączyć się z tabelą PriceType, aby uzyskać wartości Type, musisz ich użyć tylko wtedy, gdy chcesz określić sekwencję ENUMs.

Ograniczenia klucza obcego zostały wprowadzone w SQLite w wersji 3.6.19.

ChrisV
źródło
3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Powinien spowodować błąd składni. „Pierwszy formularz (ze słowem kluczowym„ VALUES ”) tworzy jeden nowy wiersz w istniejącej tabeli.” : sqlite.org/lang_insert.html . Zerwij, unikaj tego: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
Nie zapomnij PRAGMA foreign_keys = ON;o każdej sesji - ponieważ fkeys są domyślnie wyłączone w sqlite3
smathy
3
Jeśli chcesz uniknąć zapomnienia, PRAGMA foreign_keys = ON;możesz to ustawić w swoim pliku .sqliterc w swoim katalogu domowym.
Eradicatore
1
Możesz także chcieć użyć UNIQUEograniczenia dla Seq. Coś takiegoCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore
1
Dlaczego miałbyś utworzyć oddzielną kolumnę „Seq” zamiast używać tylko domyślnej kolumny rowid ?
Parthian Shot