Como criar o tipo ENUM no SQLite?

104

Preciso converter uma tabela do MySQL para SQLite, mas não consigo descobrir como converter um campo enum, porque não consigo encontrar o ENUMtipo no SQLite.

O referido campo encontra-se pTypena seguinte tabela:

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

Preciso de um campo com apenas três valores para o usuário escolher, e gostaria de impor isso no banco de dados, não apenas em meu aplicativo.

onedevteam.com
fonte

Respostas:

81

Não há tipo enum no SQLite, apenas o seguinte:

  • NULO
  • INTEIRO
  • REAL
  • TEXTO
  • BLOB

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

Receio que uma pequena tabela enum personalizada será necessária no seu caso.

MPelletier
fonte
26
Na verdade, "uma tabela enum personalizada" é um design muito mais limpo que usar enums reais
a_horse_with_no_name
19
Por que não usar a restrição CHECK () para permitir apenas três strings possíveis?
Mateusza
1
@Wideshanks eu não acho que CHECK()existia na época em que escrevi essa resposta. A menos que a corda seja muito curta, sou totalmente contra. 1 ou 2 caracteres no máximo.
MPelletier
Posso usar VARCHARna minha versão SQLite, é um novo tipo de adição?
Hamman Samuel de
3
@HammanSamuel Não é novo, é resolvido como significado TEXT. Na página de origem que apresentei, consulte o ponto 2.1 em Determinação da afinidade da coluna.
MPelletier
105

A maneira SQLite é usar uma restrição CHECK .

Alguns exemplos:

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

Isso irá limitar a pTypecoluna para apenas os valores M, Re H, assim como enum("M", "R", "H")faria em alguns outros motores de SQL.

mateusza
fonte
2
Bem, na verdade esta implementação não emula totalmente enumporque torna impossível classificar pelo índice inteiro dos valores (o que é possível com um enumcampo real ). Apenas, todos, tenham isso em mente.
Boris D. Teoharov
53

Para expandir a resposta do MPelletier, você pode criar as tabelas assim:

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

Agora, os valores de enumeração estão disponíveis diretamente na tabela Price, pois estariam usando um ENUM: você não precisa se juntar à tabela PriceType para obter os valores Type, você só precisa usá-lo se quiser determinar a sequência de os ENUMs.

As restrições de chave estrangeira foram introduzidas no SQLite versão 3.6.19.

ChrisV
fonte
3
INSERT INTO PriceType(Type, Seq) VALUES ('M',1), ('R',2), ('H',3);Você deve obter um erro de sintaxe. "A primeira forma (com a palavra-chave" VALUES ") cria uma única linha nova em uma tabela existente." : sqlite.org/lang_insert.html . Divida para evitar que: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ão se esqueça de PRAGMA foreign_keys = ON;para cada sessão - porque fkeys são desabilitadas por padrão no sqlite3
smathy
3
Se você deseja evitar o esquecimento PRAGMA foreign_keys = ON;, pode configurar isso em seu arquivo .sqliterc em seu diretório inicial.
Eradicatore
1
Além disso, você pode querer usar a UNIQUErestrição em Seq. Algo assimCREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);
Eradicatore
1
Por que você criaria uma coluna 'Seq' separada em vez de apenas usar a coluna rowid padrão ?
Parthian Shot