如何在SQLite中创建ENUM类型?

one*_*com 92 sqlite enums types

我需要将一个表从MySQL转换为SQLite,但我无法弄清楚如何转换枚举字段,因为我ENUM在SQLite中找不到类型.

上述字段pType如下表所示:

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
Run Code Online (Sandbox Code Playgroud)

我需要一个只有三个值的字段供用户选择,我想在DB中强制执行,而不仅仅是在我的应用程序中.

mat*_*sza 84

SQLite的方式

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'
)
Run Code Online (Sandbox Code Playgroud)

  • 好吧,实际上这个实现并没有完全模拟“enum”,因为它使得无法按值的整数索引进行排序(这对于实际的“enum”字段是可能的)。只是,大家记住这一点。 (5认同)
  • 存储开销也应该被视为一个警告。虽然约束可用于确保数据完整性,并且索引将使查询足够快,但您仍然存储字符串 - 如果广泛使用,这需要比适当的枚举多几倍的存储空间,具体取决于字符串长度。您可能需要考虑使用额外的查找表和外键来解决此问题。 (4认同)

MPe*_*ier 75

SQLite中没有枚举类型,只有以下内容:

  • 空值
  • 整数
  • 真实
  • 文本
  • BLOB

资料来源:http://www.sqlite.org/datatype3.html

我担心在你的情况下需要一个小的,定制的枚举表.

  • 实际上"自定义枚举表"是一种使用真实枚举的更清晰的设计 (26认同)
  • 为什么不使用CHECK()约束只允许三个可能的字符串? (16认同)
  • @Wideshanks我不认为在我写这个答案时存在`CHECK()`。除非字符串“真的”很短,否则我完全反对。最多 1 或 2 个字符。 (6认同)
  • @HammanSamuel这不是新的,它的意思是"TEXT".在我给出的源页面上,参见关于柱亲和力测定的第2.1点. (3认同)

Chr*_*isV 50

要扩展MPelletier的答案,您可以像这样创建表:

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);
Run Code Online (Sandbox Code Playgroud)

现在,枚举值可直接在Price表中使用,因为它们将使用ENUM:您不需要连接到PriceType表来获取Type值,如果要确定序列值,则只需要使用它ENUM.

SQLite版本3.6.19中引入了外键约束.

  • 不要忘记每次会话都要使用`PRAGMA foreign_keys = ON;`因为sqlite3默认禁用fkeys (9认同)
  • 为什么要创建一个单独的“Seq”列而不是仅使用默认的 [rowid 列](https://www.sqlite.org/lang_createtable.html#rowid)? (4认同)
  • 我想 Seq 列的主要用途是排序。因此,我认为最好使用 10, 20, 30... 而不是 1, 2, 3... 以便能够稍后插入一个新的枚举,该枚举应该按排序顺序出现在例如 20 到 30 之间。 (4认同)
  • `INSERT INTO PriceType(Type,Seq)VALUES('M',1),('R',2),('H',3);`应该给你一个语法错误._"第一个表单(带有"VALUES"关键字)在现有表中创建一个新行."_:https://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);` (3认同)
  • 另外,您可能想在 Seq 上使用“UNIQUE”约束。像这样的`CREATE TABLE PriceType( Type Char(1) PRIMARY KEY NOT NULL, Seq INTEGER UNIQUE);` (3认同)
  • 如果您想避免忘记`PRAGMA foreign_keys = ON;`那么您可以在主目录的.sqliterc文件中设置它. (2认同)