过去,我被告知(在这个站点上)我应该规范化数据库中的值 - 使用查找表而不是使用直接(字符串)键。
我很困惑为什么这很好,以至于有几个人推荐了这个。仅仅是为了内存消耗吗?但是在我的情况下(如下所述)那是多少?
考虑我有一个网站的字典数据库:
CREATE TABLE dictionary
(
id serial NOT NULL,
key text NOT NULL,
language text NOT NULL,
value text,
PRIMARY KEY (id)
)
Run Code Online (Sandbox Code Playgroud)
然后插入会发生如下:
INSERT INTO public.dictionary VALUES
('yes_button', 'en', 'yes'), ('yes_button', 'nl', 'ja')
Run Code Online (Sandbox Code Playgroud)
或者,我会使用“en-us”来代替“en”。现在我被告知要“规范化”数据库——这意味着有一个查找表来绑定语言的字符串表示('en'、'nl' 到一个值):
CREATE TABLE languages
(
id serial NOT NULL,
language text
)
CREATE TABLE dictionary
(
id serial NOT NULL,
key text NOT NULL,
language integer NOT NULL,
value text,
PRIMARY KEY (id),
FOREIGN KEY (language)
REFERENCES public.languages (id)
)
Run Code Online (Sandbox Code Playgroud)
然而,这会增加相当多的复杂性,因为插入不再简单——它需要检查后端的外部表,或者使用一些更复杂的 …
我有第二范式 (2NF) 的问题,我无法使用 Google 解决它。这让我发疯,因为我是一名老师,我不想教我的学生错误的东西。
让我们有一个包含 5 个字段的表。
评分 = {学生姓名、学科代码、学科名称、#考试、成绩}
依赖是这样的:
学生姓名、学科代码、#考试 -> 成绩
主题代码 -> 主题名称
主题名称 -> 主题代码
因此,候选键 1 是{StudentName, SubjectCode, #Exam},候选键 2 是{StudentName, SubjectName, #Exam}。
主要属性是{StudentName, SubjectCode, SubjectName, #Exam},非主要属性是Grade
根据第二范式的定义,非主属性不能依赖于候选键的一部分。唯一的非主要属性 (Grade) 不依赖于候选键的一部分,因此该表似乎在 2NF 中。
问题是我认为有些不对劲(我可能是错的)。我认为科目应该有自己的桌子。
评分 = {学生姓名,学科代码,#考试,成绩}
主题 = {主题代码,主题名称}
但是 2NF 不会产生这个。3NF 是关于非主要属性之间的依赖关系,因此它也不会产生这种依赖关系。但在我看来,这是正确的结果,因为它没有冗余。
我猜如果非主要属性被定义为“不是候选键的属性”,2NF 会产生想要的结果。但是我一次又一次地检查了这一点,非主要属性被定义为“不属于候选键的属性”。
我究竟做错了什么?
假设我有一个名为 的表User_FriendList,它具有以下特征:
CREATE TABLE User_FriendList (
ID ...,
User_ID...,
FriendList_IDs...,
CONSTRAINT User_Friendlist_PK PRIMARY KEY (ID)
);
Run Code Online (Sandbox Code Playgroud)
让我们假设该表包含以下数据:
+----+---------+---------------------------+ | 身份证| 用户 ID | 好友 列表_ID | +----+---------+---------------------------+ | 1 | 102 | 2:15:66:35:26:17: | +----+---------+---------------------------+ | 2 | 114 | 1:12:63:33:24:16:102 | +----+---------+---------------------------+ | 3 | 117 | 6:24:52:61:23:90:97:118 | +----+---------+---------------------------+
注:该“:”当(冒号)是分隔符爆炸在PHP成array。
问题
所以:
这是一个方便的方式来“存储”的IDs的FriendList?
或者,相反,我是否应该让FriendId每一行只有一个值,并且当我需要检索给定列表的所有行时,只需执行如下查询SELECT * FROM UserFriendList WHERE UserId = …
每两周,系统将为公司生成发票。
公司将在每月 1 日和 16 日收到发票。(它将每 2 周通过 Cron Job 运行一次。它会扫描订单表,然后添加到“发票”表中。还有其他选择吗?)
表中有客户订单列表,orders还标明了它属于哪个公司(orders.company_id)
该invoice表计算orders表中订单的总成本。
我想弄清楚如何设计合理的发票跟踪。有时公司将不得不向我发送费用或有时我向他们发送费用 ( invoice.amount)
我需要使用以下内容跟踪发票:
这是我提出的数据库设计:
公司表
mysql> select * from company;
+----+-----------+
| id | name |
+----+-----------+
| 1 | Company A |
| 2 | Company B |
+----+-----------+
Run Code Online (Sandbox Code Playgroud)
Customers can select a company from my website.
orders table
mysql> select * from orders;
+----+---------+------------+------------+---------------------+-----------+
| id | …Run Code Online (Sandbox Code Playgroud) 考虑我们有大量的统计数据作为记录;例如 20-30INT列。将整个集合保存在一个表中是否更好,因为它们都属于一个记录或创建另一个以一对一关系连接的表。
前者的优点是避免JOIN并快速访问相应记录的所有统计数据。
后者的优点是保持柱子整洁。第一列是读密集型,第二列是写密集型。当然,我认为它对性能没有显着影响,因为我使用的是行级阻塞的 InnoDB。
一般来说,我想知道为单个记录分离不同的数据集是否实用?
mysql innodb normalization database-design relational-theory
假设我有一个对象,其中包含我想要跟踪历史的某些字段和我不想跟踪历史的某些字段。从规范化的角度来看,以下模式是否正常:
CREATE TABLE MyObject AS (
MyObjectId INT IDENTITY NOT NULL PRIMARY KEY,
MyObjectField1 VARCHAR(100) NOT NULL,
MyObjectField2 VARCHAR(100) NOT NULL,
MyObjectField3 VARCHAR(100) NOT NULL,
MyObjectTrackedField1 VARCHAR(100) NOT NULL,
MyObjectTrackedField2 VARCHAR(100) NOT NULL,
MyObjectTrackedField3 VARCHAR(100) NOT NULL,
)
CREATE TABLE MyObjectHistory AS (
MyObjectHistoryId INT IDENTITY NOT NULL PRIMARY KEY,
MyObjectId INT NOT NULL FOREIGN KEY REFERENCES MyObject(MyObjectId),
MyObjectTrackedField1 VARCHAR(100) NOT NULL,
MyObjectTrackedField2 VARCHAR(100) NOT NULL,
MyObjectTrackedField3 VARCHAR(100) NOT NULL,
)
Run Code Online (Sandbox Code Playgroud)
其中 MyObjectHistory 包含除最新版本之外的所有跟踪字段。或者,是否所有跟踪字段都在一个表中,并且所有修订包括最新版本都在该表中,如下所示:
CREATE TABLE MyObject AS (
MyObjectId …Run Code Online (Sandbox Code Playgroud) 我正在制作一个小程序,用户可以在其中发表帖子或写博客。在这些帖子上,其他用户可以像在 facebook 中一样喜欢或不喜欢帖子,也可以像在 stackoverflow 中一样对帖子投赞成票或反对票。我想知道一个常用的良好数据库结构,并且该程序可以有效地使用该结构。我有两个选择
第一的
邮政:
id head message datepost likes dislikes
1 ab anchdg DATE 1,2,3 7,55,44,3
Run Code Online (Sandbox Code Playgroud)
上面的方式,id就是postid。在likes 列中,1,2,3是喜欢或upvoted 帖子或博客的用户的ID。7,55,44,3是不喜欢或贬低帖子或博客的用户的 ID。
第二
邮政:
id head message datepost
1 ab anchdg DATE
Run Code Online (Sandbox Code Playgroud)
喜欢:
id postid userid
1 1 1
2 2 2
Run Code Online (Sandbox Code Playgroud)
不喜欢:
id postid userid
1 1 7
2 1 55
Run Code Online (Sandbox Code Playgroud)
这样,我必须为喜欢和不喜欢创建两个单独的表才能获得帖子的喜欢。这样,表 ie Likes&Dislikes将被大量填满。这可能会使表格变重且处理速度变慢。
所以,我想知道哪种更好和标准的方法来完成这项任务?
我偶然发现了一个我不擅长的数据库设计问题,而我的首选 DBA 大师正在进行消防演习。
本质上,我有一个包含以下主键的表(为简洁起见,PK):
child_id integer
parent_id integer
date datetime
Run Code Online (Sandbox Code Playgroud)
child_id和parent_id是实体表的外键。“子”表本身也包含一个到“父”表的外键,而且,每个表child_id总是引用与parent_id上表预期相同的外键。事实上,事实证明有一些额外的代码使两者保持同步。
这使得这个过度热情的规范化新手说“我应该删除冗余!”
我分解为以下内容:
Table_1 PK:
child_id integer
date datetime
Table_2 PK:
parent_id integer
date datetime
Table_3: (already exists)
child_id integer PRIMARY KEY
parent_id integer FOREIGN KEY
Run Code Online (Sandbox Code Playgroud)
瞧,当我以自然的方式将这些人连接在一起时,我恢复了原始表。这是我的理解,使这个 5NF。
然而,现在我意识到有一个隐藏的商业规则。
通常,与给定关联的日期child_id必须是与相应parent_id. 您可以看到第一个表强制执行此规则。
我的分解不强制执行规则,因为您可以自由添加到表 1,直到日期变得太大。
这使我来到这里,有以下问题:
这是分解5NF吗?虽然我会说它允许插入异常,但它似乎也遵循 Wiki 示例,该示例本身遵循本指南。短语(强调我的)“我们可以从由三种不同记录类型组成的规范化形式重建所有真实事实”给了我特别的停顿,因为无论我注入多少垃圾Table_1,自然连接仍然会忽略它。
假设我不喜欢这种分解(我不喜欢)。我坦率地承认,实际的解决方案是让表格和代码保持原样。但是,从理论上讲,有没有办法分解和/或添加约束,以便我摆脱第一个表并保留我的业务规则?
schema normalization database-design best-practices relational-theory
我试图获得什么是第一范式的明确版本。我阅读的所有内容都略有不同。
许多权威,例如 Date,说根据定义,关系总是处于第一范式,而其他人则给出了要求列表。这意味着对 1NF 的要求从零到很多。
我想区别在于表和关系之间的区别:表可能是一团糟,而关系遵循某些限制。关系在 SQL 中表示为表的事实因此造成了一些混淆。
我特别关注 1NF,因为它与 SQL 数据库有关。问题是:需要什么属性来确保表处于第一范式?
许多权威建议,如果一个表代表一个关系,那么它已经在 1NF 中。这将 1NF 的定义推回到关系的定义。
以下是 1NF 中表的一些属性:
[1] 技术上属性是无序的,但在表格中,行数据必须与列标题的顺序相同。然而,实际的顺序是微不足道的。
在多个数据上:
原子数据的概念是一个项目不能被进一步分解。这个概念是有限制的,因为虽然从技术上讲,一切都可以令人厌烦地分解,但实际上不能进一步分解所讨论的数据,这取决于数据的使用方式。
例如,完整地址或全名通常应该进一步细分,但可能不应该进一步细分诸如给定名称或城镇名称之类的组件,尽管它们可以作为字符串。
至于重复的列,它是一个设计不良列具有近重复列,例如phone1,phone2等。通常,重复数据指示用于一个附加的相关表的需要。
依赖
行之间不应该有任何关系,除了它们符合相同的标题。
列之间也应该没有关系,但我相信这是更高范式的主题。
问题是:1NF 的定义中有多少上述内容?独立行位也进入了吗?
normalization ×10
mysql ×3
foreign-key ×1
innodb ×1
postgresql ×1
schema ×1
string ×1
transaction ×1