¿Cómo crear el tipo ENUM en SQLite?

104

Necesito convertir una tabla de MySQL a SQLite, pero no puedo averiguar cómo convertir un campo de enumeración, porque no puedo encontrar el ENUMtipo en SQLite.

El campo mencionado anteriormente se encuentra pTypeen la siguiente tabla:

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

Necesito un campo con solo tres valores para que el usuario elija, y me gustaría hacer cumplir eso en la base de datos, no solo en mi aplicación.

onedevteam.com
fuente

Respuestas:

81

No hay un tipo de enumeración en SQLite, solo lo siguiente:

  • NULO
  • ENTERO
  • REAL
  • TEXTO
  • GOTA

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

Me temo que se requerirá una pequeña tabla de enumeración personalizada en su caso.

MPelletier
fuente
26
En realidad, "una tabla de enumeración personalizada" es un diseño mucho más limpio que el uso de enumeraciones reales
a_horse_with_no_name
19
¿Por qué no usar la restricción CHECK () para permitir solo tres cadenas posibles?
mateusza
1
@Wideshanks No creo que CHECK()existiera en el momento en que escribí esa respuesta. A menos que la cuerda sea muy corta, estoy totalmente en contra. Máximo 1 o 2 caracteres.
MPelletier
Puedo usar VARCHARen mi versión de SQLite, ¿es una adición de nuevo tipo?
Hamman Samuel
3
@HammanSamuel No es nuevo, está resuelto como significado TEXT. En la página de origen que proporcioné, consulte el punto 2.1 sobre Determinación de la afinidad de columnas.
MPelletier
105

La forma de SQLite es usar una restricción CHECK .

Algunos ejemplos:

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

Esto limitará la pTypecolumna a solo los valores M, Ry H, tal como enum("M", "R", "H")lo haría en otros motores SQL.

mateusza
fuente
2
Bien, en realidad esta implementación no emula completamente enumporque hace que sea imposible ordenar por el índice entero de los valores (lo cual es posible con un enumcampo real ). Solo, todos, tengan eso en cuenta.
Boris D. Teoharov
53

Para expandir la respuesta de MPelletier, puede crear las tablas así:

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

Ahora los valores de enumeración están disponibles directamente en la tabla de precios, ya que estarían usando un ENUM: no necesita unirse a la tabla de tipos de precios para obtener los valores de tipo, solo necesita usarlos si desea determinar la secuencia de los ENUM.

Las restricciones de clave externa se introdujeron en SQLite versión 3.6.19.

ChrisV
fuente
3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Debería darte un error de sintaxis. "El primer formulario (con la palabra clave" VALUES ") crea una única fila nueva en una tabla existente". : 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);
Romperlo
9
No se olvide de PRAGMA foreign_keys = ON;para cada sesión, porque las teclas f están deshabilitadas de forma predeterminada en sqlite3
smathy
3
Si desea evitar olvidar PRAGMA foreign_keys = ON;, puede configurarlo en su archivo .sqliterc en su directorio de inicio.
Eradicatore
1
Además, es posible que desee utilizar la UNIQUErestricción en Seq. Algo como estoCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore
1
¿Por qué crearía una columna 'Seq' separada en lugar de simplemente usar la columna de ID de fila predeterminada ?
Disparo parto