Comment créer un type ENUM dans SQLite?

105

J'ai besoin de convertir une table de MySQL en SQLite, mais je ne peux pas comprendre comment convertir un champ d'énumération, car je ne trouve pas de ENUMtype dans SQLite.

Le champ susmentionné est pTypedans le tableau suivant:

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

J'ai besoin d'un champ avec seulement trois valeurs que l'utilisateur doit choisir, et je voudrais appliquer cela dans la base de données, pas seulement dans mon application.

onedevteam.com
la source

Réponses:

81

Il n'y a pas de type enum dans SQLite, uniquement ce qui suit:

  • NUL
  • ENTIER
  • RÉEL
  • TEXTE
  • GOUTTE

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

J'ai peur qu'une petite table d'énumération personnalisée soit requise dans votre cas.

MPelletier
la source
26
En fait, "une table d'énumération personnalisée" est une conception beaucoup plus propre qui utilise des
énumérations
19
Pourquoi ne pas utiliser la contrainte CHECK () pour n'autoriser que trois chaînes possibles?
mateusza
1
@Wideshanks Je ne pense pas qu'il CHECK()existait au moment où j'ai écrit cette réponse. À moins que la corde ne soit vraiment courte, je suis totalement contre. 1 ou 2 caractères maximum.
MPelletier
Je peux utiliser VARCHARdans ma version SQLite, est-ce un nouveau type d'ajout?
Hamman Samuel
3
@HammanSamuel Ce n'est pas nouveau, c'est résolu comme un sens TEXT. Sur la page source que j'ai donnée, voir le point 2.1 sur la détermination de l'affinité de colonne.
MPelletier
106

La méthode SQLite consiste à utiliser une contrainte CHECK .

Quelques exemples:

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

Cela limitera la pTypecolonne aux seules valeurs M, Ret H, comme le enum("M", "R", "H")ferait certains autres moteurs SQL.

mateusza
la source
2
Eh bien, en fait, cette implémentation n'émule pas complètement enumcar elle rend impossible le tri par index entier des valeurs (ce qui est possible avec un enumchamp réel ). Juste, tout le monde, gardez cela à l'esprit.
Boris D. Teoharov
53

Pour développer la réponse de MPelletier, vous pouvez créer les tableaux comme ceci:

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

Désormais, les valeurs d'énumération sont disponibles directement dans la table Price car elles utiliseraient un ENUM: vous n'avez pas besoin de vous joindre à la table PriceType pour obtenir les valeurs Type, vous devez uniquement l'utiliser si vous souhaitez déterminer la séquence de les ENUM.

Les contraintes de clé étrangère ont été introduites dans la version 3.6.19 de SQLite.

ChrisV
la source
3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Devrait vous obtenir une erreur de syntaxe. "Le premier formulaire (avec le mot clé" VALUES ") crée une seule nouvelle ligne dans une table existante." : sqlite.org/lang_insert.html . Brisez-le, évitez cela: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
N'oubliez pas de le faire PRAGMA foreign_keys = ON;pour chaque session - car les touches fkeys sont désactivées par défaut dans sqlite3
smathy
3
Si vous voulez éviter d'oublier, PRAGMA foreign_keys = ON;vous pouvez le configurer dans votre fichier .sqliterc dans votre répertoire personnel.
Eradicatore
1
En outre, vous souhaiterez peut-être utiliser la UNIQUEcontrainte sur Seq. Quelque chose comme çaCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore
1
Pourquoi créeriez- vous une colonne «Seq» distincte au lieu d'utiliser simplement la colonne rowid par défaut ?
Parthe Shot