我必须维护一个应用程序,该应用程序具有许多文本数据类型的列,其中插入了多个值,以逗号、斜杠或有时甚至是管道 (|) 字符分隔。我试图弄清楚为什么你会想要这样做。
例如,订单表有一个名为 details 的列,其中包含以下信息:
2x #ABC-12345 Widget, Black: $24.99 /4x #ABC-12344 Widget, Blue: $23.50
哪里
/
分隔行项目;有 VBScript 代码从记录集中读取值并在 For
中解析它。使用类似的循环显示(这几乎就是代码读取的方式,变量名和所有内容)arydtls = split(rstmp("details"), "/")
.此方法在各种表的整个代码中重复出现。在我看来,将详细信息放在单独的表中并链接回它会好 100 倍(更不用说更容易使用)(有趣的是,对于订单它 做 这样做,但数据并不总是与详细信息文本字段匹配,因为 OrderDetail 表在代码中更新;详细信息字段在应用程序中被视为只读)。
我的前任知道我不知道的事情,还是我说“WTF?!!”当我看这个模式时?看起来像这样非常低效且难以维护,并且它使运行报告变得更加困难,因为我需要的数据可能包含在文本字段中,或者它可能位于十几个具有相似信息并用于不同的表中的一个表中应用程序的一部分。
最佳答案
Did my predecessor know something I didn't, or am I right to be saying "WTF?!!" when I look at this schema?
不,你的前任没有。你是对的。但是,请参阅最后的注释。
It seems like it's insanely inefficient and difficult to maintain like this, and it makes running reports extra difficult because the data I need could be contained in text fields OR it might be in one of a dozen tables that have similar information and are used in different parts of the application.
这是非常低效的。但是,请参阅最后的注释。
列应该始终是行的不可分割的属性。我在您展示的这一列中看到了三个(可能是四个)属性的两个副本:
2x #ABC-12345 Widget, Black: $24.99 /4x #ABC-12344 Widget, Blue: $23.50
这本来可以更好地设计为:
StockItems
Code char(10) primary key
Desc varchar(50)
Transaction
TxnId something primary key
: : :
TransactionPart
TxnId something \
TxnSeq int / primary key
Quantity integer
Code char(10) foreign key StockItems(Code)
Price float
注意:
这样做可能是为了在数据库中其他地方的值发生变化时保留历史信息。例如,如果库存项目的描述更改或项目被删除。
然而,这仍然不是正确的处理方式。在这种情况下,外键约束会阻止项目代码被删除,并且应该有流程来防止更新描述(例如对库存项目代码进行版本控制)。
当然,如果您永远不会搜索该列中的任何项目,这是完全有效的,尽管就可能的 future 搜索功能而言是不明智的。
也许在此表中搜索过的唯一内容是客户代码 - 那么自由格式的文本字段就足够了。
我仍然不会那样做,但是可以提出一个 YAGNI 论点,即如果需要添加该搜索功能以及何时需要添加该搜索功能,那么将来更改数据库架构会更好。
关于database-design - 为什么要在 SQL 文本列中存储分隔列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/532927/