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.

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ń.


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.


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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.