2009-04-17 62 views
18

如何在不支持枚举的数据库中实现枚举字段? (即SQLite)如何处理数据库中没有枚举字段的枚举?

这些字段需要用“field =?”轻松搜索。所以使用任何类型的数据序列化都不是一个好主意。

+0

如果这是重复的,请保持好心情。在我询问之前,我确实在StackOverflow上寻找了答案。 – epochwolf 2009-04-17 16:47:20

回答

49

使用外键到查找表是我使用的方法。事实上,即使我使用支持ENUM的数据库(例如MySQL),我也会使用它。

为了简单起见,我可以跳过查找表中不断出现的“id”,只是使用我在主表中需要的实际值作为查找表的主键。这样你就不需要进行连接来获得价值。

CREATE TABLE BugStatus (
    status   VARCHAR(20) PRIMARY KEY 
); 

INSERT INTO BugStatus (status) VALUES ('NEW'), ('OPEN'), ('FIXED'); 

CREATE TABLE Bugs (
    bug_id   SERIAL PRIMARY KEY, 
    summary   VARCHAR(80), 
    ... 
    status   VARCHAR(20) NOT NULL DEFAULT 'NEW', 
    FOREIGN KEY (status) REFERENCES BugStatus(status) 
); 

诚然,存储字符串需要更多的空间比MySQL的执行ENUM,但除非有问题的表有数百万行,这并不重要。

查找表的其它优点是,你可以添加或用一个简单的INSERTDELETE从列表中删除一个值,而与ENUM你必须使用ALTER TABLE重新定义列表。

也尝试查询ENUM中允许值的当前列表,例如在用户界面中填充选取列表。这是一个主要的烦恼!通过查找表,很容易:SELECT status from BugStatus

如果需要(例如标记仅供管理员使用的选项),还可以将其他属性列添加到查找表中。在ENUM中,您不能注释条目;他们只是简单的价值观。

除了查找表的另一种选择是使用CHECK约束(提供数据库支持他们 - MySQL不):

CREATE TABLE Bugs (
    bug_id   SERIAL PRIMARY KEY, 
    summary   VARCHAR(80), 
    ... 
    status   VARCHAR(20) NOT NULL 
    CHECK (status IN ('NEW', 'OPEN', 'FIXED')) 
); 

但这使用CHECK约束来自同一患有缺点如ENUM:很难更改值列表而不使用ALTER TABLE,难以查询允许值列表,难以注释值。

PS:SQL中的相等比较运算符是单个=。双重==在SQL中没有意义。

+0

感谢=对比==的东西:)直到我使用SQL已经有一段时间了。 – epochwolf 2009-04-17 23:20:02

+0

很好的答案,从我+1。 – Brann 2009-04-18 07:25:06

-1

我会使用一个varchar。这不适合你吗?

+0

使用VARCHAR会导致非规格化的数据。如果要更改枚举值的名称,它需要在整个表上进行更新,而不仅仅是更改参考表中的单个行。 – 2009-04-17 17:23:18

1

你基本上有两种选择:

  • 使用整型字段

  • 使用VARCHAR场

我个人主张用VARCHAR处理的,因为你不会如果你改变你的enum +这些字段是人类可读的,但是int也有一些专业知识,也就是性能(数据的大小是一个明显的例子),所以不会破坏任何东西

2

要限制可能的值,我将使用外键来保存枚举项目的表。

如果你不想加入去做你的搜索,那么把键设为varchar如果JOINS不是问题,那么将键设为INT并且不加入,除非你需要在该字段上搜索。

请注意,将枚举放入数据库将排除编译时检查代码中的值(除非在代码中复制枚举)。我发现这是一个很大的缺陷。

0

这是我最近

在我的休眠映射POJO-我不停的成员作为字符串类型,它是VARCHAR在数据库中。

这种情况的发生二传手枚举 还有一个二传手这需要与字符串但这是私人(或如果这就是你喜欢什么,你可以映射场两个直。)

现在其实我使用字符串从所有封装。对于其他应用程序 - 我的域对象使用枚举。 就数据库而言,我正在使用String。

如果我错过了你的问题,我很抱歉。