Sql 6NF中引用完整性的复合键与代理键
获取三层信息: 第1层:信息 该层包含具有Sql 6NF中引用完整性的复合键与代理键,sql,database,6nf,Sql,Database,6nf,获取三层信息: 第1层:信息 该层包含具有唯一自然索引的数据和易于传输的代理键 Table Surnames: +-----------------------------+--------------+ | ID (Auto Increment, PK) | Surname | +-----------------------------+--------------+ | 1 | Smith | |
唯一
自然索引的数据和易于传输的代理键
Table Surnames:
+-----------------------------+--------------+
| ID (Auto Increment, PK) | Surname |
+-----------------------------+--------------+
| 1 | Smith |
| 2 | Edwards |
| 3 | Brown |
+-----------------------------+--------------+
Table FirstNames
+-----------------------------+--------------+
| ID (Auto Increment, PK) | FirstName |
+-----------------------------+--------------+
| 1 | John |
| 2 | Bob |
| 3 | Mary |
| 4 | Kate |
+-----------------------------+--------------+
自然关键点
create table people (
FirstName integer not null
references FirstNames (ID),
LastName integer not null
references Surnames (ID),
primary key (FirstName, LastName)
);
create table people (
FirstName varchar(n) not null
references FirstNames (FirstName),
LastName varchar(n) not null
references Surnames (Surname),
primary key (FirstName, Surname)
);
或者,上面的两个表可以没有ID
,并使用姓氏和名字作为自然主键,如Mike Sherrill所解释的。在本例中,假设下面的层引用的是varchar
,而不是int
第二层:人
在这一层中使用了一个综合索引。此值可以是唯一的
或主键
,具体取决于是否将代理键用作主键
+-----------------+--------------+
| FirstName | LastName |
+-----------------+--------------+
| 1 | 2 |
| 1 | 3 |
| 2 | 3 |
| 3 | 1 |
| 4 | 2 |
| ... | ... |
+-----------------+--------------+
第三层:父母
在这一层中,人与人之间的关系通过ParentsOf
表进行探索
ParentsOf
+-----------------+-----------------+
| Person | PersonParent |
+-----------------+-----------------+
OR
+-----------------+-----------------+-----------------+-----------------+
| PersonFirstName | PersonSurname | ParentFirstName | ParentSurname |
+-----------------+-----------------+-----------------+-----------------+
问题
假设引用完整性在其核心对我来说非常重要,我将在这些索引上有外键
,这样我就可以让数据库负责在这方面监控其自身的完整性,并且,如果我要使用ORM,它将是一个对复合主键具有本机支持的ORM
请帮助我理解:
- 在第1层上使用代理关键点与自然关键点的权衡列表
- 在第二层上使用复合键与代理键(可以转移到第三层)的权衡列表
+-----------------------------+--------------+
| Grocery | Brand |
+-----------------------------+--------------+
| Sponges | Bright |
| Ice Cream | Ben & Jerry's|
| Ice Cream | Store Brand |
| Tomato Soup | Campbell's |
| Tomato Soup | Store Brand |
| Lemons | Store Brand |
| Whipped Cream | Cool Whip |
+-----------------------------+--------------+
推荐配对
+-----------------+-----------------+-----------------+-----------------+
| Grocery1 | Brand1 | Grocery2 | Brand2 |
+-----------------+-----------------+-----------------+-----------------+
重申一下,这也只是一个例子。我不建议这样做,但这应该有助于说明我的问题
这种方法有不足之处。我要重申,这个问题是要求我们仔细分析下面每种方法的优缺点,而不是强调一种方法比另一种方法好。我相信大多数人都能够通过这个具体例子的可疑性质来回答核心问题。此编辑适用于无法编辑的对象
下面有一些很好的答案,如果你想知道该往哪个方向走,请阅读
结束编辑
谢谢大家! 以下是一些权衡: 单个代理(人工创建):
- 所有子表外键只需要一列来引用主键
- 非常容易更新表中的自然键,而无需使用外键更新每个子表
- 较小的主键/外键索引(即不宽)这可以使数据库运行更快,例如,当父表中的记录被删除时,需要搜索子表以确保不会创建孤立项。窄索引的扫描速度更快(非常明显)
- 您将拥有更多索引,因为您很可能还希望索引数据中存在的任何自然键
- 数据库中的索引更少
- 数据库中的列更少
- 插入大量记录更容易/更快,因为您无需获取序列生成器
- 更新组合中的一个键需要更新每个子表
客户机id
字段,则您正在创建一个行级安全环境。大多数数据库都具有在正确设置时强制执行行级安全性的工具
首先要做的是设置主键和外键。通常,具有id
字段作为主键的表。通过添加client\u id
密钥现在是复合密钥。并且必须将客户机id
携带到所有子表中
复合密钥基于2个代理密钥,是一种防弹方法,可确保客户端之间以及整个数据库内的数据完整性
在此之后,您将创建视图(或者如果使用Oracle EE设置虚拟专用数据库)和其他各种结构,以允许数据库强制执行行级安全性(这是它自己的主题)
假定此数据结构不再规范化为第n级。每个pk/fk中的client_id
字段对正常模型进行反规范化。该模型的好处是易于在数据库级别强制执行行级别的安全性(这是数据库应该做的)。每次选择、插入、更新和删除都仅限于当前设置的会话。该数据库具有create table people (
FirstName varchar(n) not null
references FirstNames (FirstName),
LastName varchar(n) not null
references Surnames (Surname),
primary key (FirstName, Surname)
);
create table people (
ID serial primary key,
FirstName integer not null
references FirstNames (ID),
LastName integer not null
references Surnames (ID),
unique (FirstName, LastName)
);
create table people (
ID serial primary key,
FirstName varchar(n) not null
references FirstNames (FirstName),
LastName varchar(n) not null
references Surnames (Surname),
unique (FirstName, Surname)
);
create table ParentsOf (
PersonFirstName integer not null,
PersonSurname integer not null,
foreign key (PersonFirstName, PersonSurname)
references people (FirstName, LastName),
ParentFirstName integer not null,
ParentSurname integer not null,
foreign key (ParentFirstName, ParentSurname)
references people (FirstName, LastName),
primary key (PersonFirstName, PersonSurname, ParentFirstName, ParentSurname)
);
create table ParentsOf (
PersonFirstName varchar(n) not null,
PersonSurname varchar(n) not null,
foreign key (PersonFirstName, PersonSurname)
references people (FirstName, LastName),
ParentFirstName varchar(n) not null,
ParentSurname varchar(n) not null,
foreign key (ParentFirstName, ParentSurname)
references people (FirstName, LastName),
primary key (PersonFirstName, PersonSurname, ParentFirstName, ParentSurname)
);
create table ParentsOf (
Person integer not null
references People (ID),
PersonParent integer not null
references People (ID),
primary key (Person, PersonParent)
);
update surnames
set surname = 'Smythe'
where surname = 'Smith';
CHECK ( jobtitle <> 'BOSS' OR salary > 100 )
ID Name Value DeletedFlag
1 Smith 78 0
2 Martin 98 0
3 John 78 1
4 Edouard 54 0
5 John 64 0
STUDENT COURSE
1 CS101
1 CS101