cwe*_*ton 14 sql database lookup database-normalization
我发现这很多,我不确定接近它的最佳方法.
我的问题是如何在使用外键查找表或直接在请求它的表中使用查找表值之间做出决定,完全避免查找表关系.
要记住的要点:
使用第二种方法,如果在查找表中更改了数据,则需要对引用数据的所有记录进行批量更新.
这更侧重于有很多列引用许多查找表的表.因此,每次查询表时,许多外键意味着很多连接.
这里有最佳实践,还是需要考虑的关键点?
Bil*_*win 28
您可以将查找表与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
);
Run Code Online (Sandbox Code Playgroud)
该解决方案具有以下优点:
令我惊讶的是,在这个线程上有这么多其他人似乎错误地认为"正常化"是什么.使用代理键(无处不在的"id")与规范化无关!
来自@MacGruber的评论:
是的,尺寸是一个因素.例如,在InnoDB中,每个二级索引都存储发生给定索引值的行的主键值.因此,您拥有的二级索引越多,为主键使用"庞大"数据类型的开销就越大.
这也会影响外键; 外键列必须与它引用的主键具有相同的数据类型.您可能有一个小的查找表,因此您认为50行表中的主键大小无关紧要.但是该查找表可能会被其他表中的数百万或数十亿行引用!
所有案件都没有正确的答案.对于不同的情况,任何答案都是正确的.您只需了解权衡,并尝试根据具体情况做出明智的决定.
在简单原子值的情况下,我倾向于不同意这一基本知识,主要是在复杂性方面。考虑一张包含帽子的桌子。您可以执行“非规范化”方式:
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" */
)
Run Code Online (Sandbox Code Playgroud)
或者,您可以通过制作“颜色”表来对其进行标准化:
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)
)
Run Code Online (Sandbox Code Playgroud)
后者的最终结果是您增加了一些复杂性-而不是:
SELECT * FROM Hat
Run Code Online (Sandbox Code Playgroud)
您现在必须说:
SELECT * FROM Hat H INNER JOIN Color C ON H.color_id = C.color_id
Run Code Online (Sandbox Code Playgroud)
那额外的加入是一笔大买卖吗?否-实际上,这是关系设计模型的基础-规范化允许您防止数据中可能出现的不一致。但是,每一种这样的情况都会增加一点点复杂性,除非有充分的理由,否则值得问一问为什么这么做。我认为可能的“充分理由”包括:
如果这些都不适用,我将很难找到另一个(好的)归一化的理由。如果您只是想确保该值是某个(较小)合法值集中的一个,则最好使用CONSTRAINT,该值表示该值必须在特定列表中。使事情保持简单,如果需要,您以后随时可以“升级”到单独的表。