我发现这很多,我不确定接近它的最佳方式。
我的问题是如何在使用外键查找表或直接在请求它的表中使用查找表值之间做出决定,完全避免查找表关系。
要记住的要点:
使用第二种方法 需要对所有人进行大规模更新 记录引用数据的记录 在查找表中更改。
这是更重点 对于有很多的表 该列引用了许多查找 table.Therefore很多外国人 钥匙意味着很多 每次查询时都加入 表
这里有最佳做法,还是需要考虑的关键点?
答案 0 :(得分:27)
您可以使用带有VARCHAR主键的查找表,并且主数据表在其列上使用FOREIGN KEY,并进行级联更新。
CREATE TABLE ColorLookup (
color VARCHAR(20) PRIMARY KEY
);
CREATE TABLE ItemsWithColors (
...other columns...,
color VARCHAR(20),
FOREIGN KEY (color) REFERENCES ColorLookup(color)
ON UPDATE CASCADE ON DELETE SET NULL
);
该解决方案具有以下优点:
令我惊讶的是,在这个问题上有这么多其他人似乎错误地认为“正常化”是什么。使用代理键(无处不在的“id”)与规范化无关!
来自@MacGruber的评论:
是的,尺寸是一个因素。例如,在InnoDB中,每个二级索引都存储发生给定索引值的行的主键值。因此,您拥有的二级索引越多,为主键使用“庞大”数据类型的开销就越大。
这也会影响外键;外键列必须与它引用的主键具有相同的数据类型。您可能有一个小的查找表,因此您认为50行表中的主键大小无关紧要。但该查找表可能被其他表中的数百万或数十亿行引用!
所有案件都没有正确答案。对于不同的情况,任何答案都是正确的。您只需了解权衡,并尝试根据具体情况做出明智的决定。
答案 1 :(得分:4)
在简单的原子价值的情况下,我倾向于不同意这一点的共同智慧,主要是复杂性方面。考虑一个包含帽子的桌子。你可以采用“非规范化”的方式:
CREATE TABLE Hat (
hat_id INT NOT NULL PRIMARY KEY,
brand VARCHAR(255) NOT NULL,
size INT NOT NULL,
color VARCHAR(30) NOT NULL /* color is a string, like "Red", "Blue" */
)
或者你可以通过制作一个“颜色”表来进一步规范它:
CREATE TABLE Color (
color_id INT NOT NULL PRIMARY KEY,
color_name VARCHAR(30) NOT NULL
)
CREATE TABLE Hat (
hat_id INT NOT NULL PRIMARY KEY,
brand VARCHAR(255) NOT NULL,
size INT NOT NULL,
color_id INT NOT NULL REFERENCES Color(color_id)
)
后者的最终结果是你增加了一些复杂性 - 而不是:
SELECT * FROM Hat
你现在必须说:
SELECT * FROM Hat H INNER JOIN Color C ON H.color_id = C.color_id
这个额外加入是一笔巨额交易吗?不 - 实际上,这是关系设计模型的基础 - 规范化允许您防止数据中可能的不一致。但是像这样的每种情况都会增加一点点的复杂性,除非有充分的理由,否则值得问你为什么这样做。我认为可能有“好理由”包括:
如果这些都不适用,我很难找到另一个(好的)归一化的理由。如果您只想确保该值是特定(小)合法值集合之一,那么最好使用CONSTRAINT,该值表示该值必须位于特定列表中;保持简单,如果需要,您可以随时“升级”到单独的表格。
答案 2 :(得分:3)
没有人考虑的一件事是,如果其中的数据随时间变化并且加入的记录是历史记录,则不会加入查找表。该示例是零件表和订单表。供应商可能会丢弃零件或更改零件编号,但订单表应该是alawys具有订购时所订购的零件。因此,它应该查找数据以执行记录插入,但是不应该连接到查找表以获取有关现有订单的信息。相反,零件号,描述和价格等应存储在订单表中。这在某种程度上是至关重要的,因此价格变化不会通过历史数据传播并使您的财务记录不准确。在这种情况下,您还希望避免使用任何类型的级联更新。
答案 3 :(得分:2)
rauhr.myopenid.com wrote:
我们决定解决这个问题的方式是第4种正常形式。 ...
这不是第4范式。这是一个常见的错误,称为One True Lookup: http://www.dbazine.com/ofinterest/oi-articles/celko22
答案 4 :(得分:1)
规范化在数据库中被普遍认为是最佳实践的一部分,规范化说是的,你将数据推出并通过密钥引用它。
答案 5 :(得分:1)
您甚至可以规定始终针对视图进行编程,让视图获得查找。
这样可以优化视图并使代码能够抵抗表中的更改。
在oracle中,如果需要,甚至可以将视图转换为物化视图。
答案 6 :(得分:0)
由于没有其他人解决了你的第二点:当查询变得冗长且由于所有这些连接而难以读写时,视图通常会解决这个问题。