假设我提供4种服务类型(它们不太可能经常更改):
- 测试中
- 设计
- 程式设计
- 其他
假设我有60-80个实际服务,每个服务都属于上述类别之一。例如,“服务”可以是“使用技术A的测试程序”,并且类型为“测试”。
我想将它们编码到数据库中。我想出了一些选择:
选项0:
使用VARCHAR
直接直接编码的业务类型为字符串
选项1:
使用数据库enum
。但是,枚举是邪恶的
选项2:
使用两个表:
service_line_item (id, service_type_id INT, description VARCHAR);
service_type (id, service_type VARCHAR);
我什至可以享受参照完整性:
ALTER service_line_item
ADD FOREIGN KEY (service_type_id) REFERENCES service_type (id);
听起来不错,是吗?
但是我仍然必须对事物进行编码并处理整数,即在填充表时。或者在填充或处理表时必须创建精心设计的程序或数据库结构。即,在直接处理数据库或在编程端创建新的面向对象的实体并确保我正确操作它们时,可以使用JOIN。
选项3:
不使用enum
,不使用两个表,而只使用一个整数列
service_line_item (
id,
service_type INT, -- use 0, 1, 2, 3 (for service types)
description VARCHAR
);
这就像一个“伪枚举”,在事物的代码方面需要更多的开销,例如知道{2 == 'Programming'}
并适当地处理它。
题:
目前,我已经在概念的指导下使用选项2实现了它
- 不要使用枚举(选项1)
- 避免将数据库用作电子表格(选项0)
但是我不禁觉得这对我而言在编程和认知开销方面是浪费的-我必须知道两个表,并且处理两个表,而不是一个。
我正在寻找一种“不浪费的方式” Option 3
。IT更轻巧,并且需要基本相同的代码结构来进行操作(稍作修改,但复杂度和结构基本相同,但只有一个表)
我认为理想情况下,它并不总是浪费,并且每种选择都有很好的案例,但是关于何时应该使用选项2和何时使用选项3是否有很好的指南?
当只有两种类型(二进制)时
为了进一步解决这个问题,在同一地点,我有一个二进制选项“标准”或“例外”服务,该选项可以应用于服务订单项。我已经使用Option 3对其进行了编码。
我选择不创建新表只是为了保存值{“ Standard”,“ Exception”}。所以我的列只保存{0,1}并且我的列名叫做exception
,并且我的代码正在执行翻译{0, 1} => {STANDARD, EXCEPTION}
(我将其编码为编程语言中的常量)
到目前为止,也不喜欢这种方式.....(不喜欢选项2或选项3)。我确实发现选项2优于3,但是开销更大,而且无论我使用2和3中的哪个选项,我仍然无法逃避将数据编码为整数的事情。
ORM
要添加一些上下文,请在阅读答案后-我刚刚(最近)开始使用ORM(在我的案例中是Doctrine 2)。通过注释定义数据库模式后,我想填充数据库。由于我的整个数据集相对较小,因此我想尝试使用编程构造来查看其工作原理。
我先填充service_type
s,然后填充s,service_line_item
因为实际电子表格中已有列表。因此,“标准/例外”和“测试”之类的东西都是电子表格上的字符串,在将它们存储在数据库中之前必须将它们编码为正确的类型。
我找到了这样的答案:在doctrine2中,您用什么代替ENUM?,建议不要使用DB的enum构造,而应使用INT
字段并使用编程语言的“ const”构造对类型进行编码。
但是正如上面的SO问题所指出的,一旦定义了整数,我就可以避免直接使用整数并使用语言构造-常量...。
但是仍然..无论您如何转动它,如果我string
以一种类型开头,即使使用ORM时,也必须首先将其转换为正确的类型。
因此,如果说$str = 'Testing';
,我仍然需要在某个地方执行以下操作:
switch($str):
{
case 'Testing': $type = MyEntity::TESTING; break;
case 'Other': $type = MyEntity::OTHER; break;
}
好的事情是您没有处理整数/魔术数(而是处理编码的常量),但是坏的事情是,如果没有此转换步骤,您将无法自动魔术地将数据放入数据库或从数据库中取出。知识。
这就是我的部分意思,是说诸如“仍然必须对事物进行编码并处理整数”之类的事情。(现在,在Ocramius发表评论后,我将不必直接处理整数,而可以根据需要处理命名常量和从常量到常量的某种转换)。