Come creare il tipo ENUM in SQLite?


105

Ho bisogno di convertire una tabella da MySQL a SQLite, ma non riesco a capire come convertire un campo enum, perché non riesco a trovare il ENUMtipo in SQLite.

Il campo di cui sopra è pTypenella seguente tabella:

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

Ho bisogno di un campo con solo tre valori che l'utente possa scegliere e vorrei applicarlo nel DB, non solo nella mia applicazione.

Risposte:


81

Non esiste alcun tipo di enum in SQLite, solo il seguente:

  • NULLO
  • NUMERO INTERO
  • VERO
  • TESTO
  • BLOB

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

Temo che nel tuo caso sia necessaria una piccola tabella enum personalizzata.


26
In realtà "una tabella di enumerazione personalizzata" è un design molto più pulito che utilizza enumerazioni reali
a_horse_with_no_name

19
Perché non utilizzare il vincolo CHECK () per consentire solo tre possibili stringhe?
mateusza

1
@Wideshanks Non credo che CHECK()esistesse al momento in cui ho scritto quella risposta. A meno che la stringa non sia molto corta, sono totalmente contrario. 1 o 2 caratteri al massimo.
MPelletier

Posso usare VARCHARnella mia versione SQLite, è una nuova aggiunta di tipo?
Hamman Samuel,

3
@HammanSamuel Non è nuovo, è risolto come significato TEXT. Nella pagina di origine che ho fornito, vedere il punto 2.1 sulla determinazione dell'affinità di colonna.
MPelletier

106

Il modo SQLite consiste nell'usare un vincolo CHECK .

Qualche esempio:

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

Questo limiterà la pTypecolonna solo i valori M, Re H, proprio come enum("M", "R", "H")farebbe in alcuni altri motori SQL.


2
Welp, in realtà questa implementazione non emula completamente enumperché rende impossibile l'ordinamento in base all'indice intero dei valori (cosa possibile con un enumcampo effettivo ). Solo, tutti, tenetelo a mente.
Boris D. Teoharov

53

Per espandere la risposta di MPelletier, puoi creare le tabelle in questo modo:

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

Ora i valori di enumerazione sono disponibili direttamente nella tabella Price poiché utilizzerebbero un ENUM: non è necessario unirsi alla tabella PriceType per ottenere i valori Type, è sufficiente utilizzarlo se si desidera determinare la sequenza di gli ENUM.

I vincoli di chiave esterna sono stati introdotti nella versione 3.6.19 di SQLite.


3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Dovresti ottenere un errore di sintassi. "Il primo modulo (con la parola chiave" VALUES ") crea una singola nuova riga in una tabella esistente." : 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);
Spezzalo,

9
Non dimenticare di farlo PRAGMA foreign_keys = ON;per ogni sessione, perché i tasti fkeys sono disabilitati di default in sqlite3
smathy

3
Se vuoi evitare di dimenticartene PRAGMA foreign_keys = ON;, puoi impostarlo nel tuo file .sqliterc nella tua home directory.
Eradicatore

1
Inoltre, potresti voler utilizzare il UNIQUEvincolo su Seq. Qualcosa di simileCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore

1
Perché dovresti creare una colonna "Seq" separata invece di utilizzare solo la colonna rowid predefinita ?
Parthian Shot
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.