支持在表定义中使用代理键
感谢@Branko Dimitrijevic 通过描述SURROGATE KEYS 的角色并进入讨论中心来打开关系数据库主键(PK)的主题。根据定义,代理键除了它们在表的每条记录中的值之间的唯一性之外没有任何内在含义。
也感谢@Mattias Åslund 的额外智慧:
请注意,只要有足够的时间,大多数“永远不会改变”的事情都会改变,比如某人的社会安全号码......
我补充说,即使选择为“不可更改”的值确实没有改变,受支持的业务或组织本身的规则也很可能随着时间的推移以可能影响核心假设的方式漂移和变化给定的设计。
Computer Professionals for Social Responsibility 在 Choosing an Appropriate Key for New Databases 上的本部分中可以找到有关集成人口统计和生物特征关键值以跟踪个人的有用讨论。
备用唯一数据库键的案例:示例架构
我计划与这篇文章中的 cmets 讨论一个特定的示例设计,以解释分配 不是 代理键的主键可能会出错的各种事情。其中许多假设取自实际应用的观察结果。由于其他系统和数据源变得依赖于他们的假设,他们的设计引入其他业务流程的复杂性被人们铭记。
设计和示例数据如下,大致借鉴了 Oracle 臭名昭著的 Scott/TIGER 数据库设计。
SQL Fiddle
MySQL 5.5.32 架构设置:
CREATE TABLE employee
(
fake_ssn varchar(15) primary key,
last_name varchar(40),
first_name varchar(40),
dept_id varchar(15),
hire_date date,
salary int,
email varchar(100)
);
INSERT INTO employee
(fake_ssn, last_name, first_name, dept_id, hire_date, salary,
email)
VALUES
('130-60-0101', 'MARLOWE', 'JACOB', '1200-05', date('2009/01/25'),
8000, 'jacob@some-company.com'),
('967-22-5025', 'CRACHITT', 'BOB', '1200-05', date('2010/02/05'),
500, 'bobc@some-company.com'),
('040-36-5555', 'PERRY', 'VICTORIA', '1200-02', date('2011/05/25'),
2700, 'vperry@some-company.com'),
('203-89-1010', 'STEVENS', 'KEVIN', '2955-03', date('2007/04/25'),
1800, 'kevin.stevens@some-company.com'),
('409-99-1111', 'MCLANE', 'JONATHAN', '2955-03', date('2009/03/02'),
4200, 'jon.j.mclane@some-company.com');
CREATE TABLE department
(
dept_id varchar(15) primary key,
dept_manager varchar(40),
dept_title varchar(40)
);
INSERT INTO department
(dept_id, dept_manager, dept_title)
VALUES
('1200-05', 'MARLOWE', 'FINANCE'),
('1200-02', null, 'HR'),
('2955-03', 'JOHNM', 'MARKETING');
COMMIT;
查询 1:
SELECT fake_ssn, last_name, first_name, dept_id, hire_date,
salary, email
FROM employee
Results:
| FAKE_SSN | LAST_NAME | FIRST_NAME | DEPT_ID | HIRE_DATE | SALARY | EMAIL |
|-------------|-----------|------------|---------|---------------------------------|--------|--------------------------------|
| 040-36-5555 | PERRY | VICTORIA | 1200-02 | May, 25 2011 00:00:00+0000 | 2700 | vperry@some-company.com |
| 130-60-0101 | MARLOWE | JACOB | 1200-05 | January, 25 2009 00:00:00+0000 | 8000 | jacob@some-company.com |
| 203-89-1010 | STEVENS | KEVIN | 2955-03 | April, 25 2007 00:00:00+0000 | 1800 | kevin.stevens@some-company.com |
| 409-99-1111 | MCLANE | JONATHAN | 2955-03 | March, 02 2009 00:00:00+0000 | 4200 | jon.j.mclane@some-company.com |
| 967-22-5025 | CRACHITT | BOB | 1200-05 | February, 05 2010 00:00:00+0000 | 500 | bobc@some-company.com |
查询 2:
SELECT dept_id, dept_manager, dept_title
FROM department
Results:
| DEPT_ID | DEPT_MANAGER | DEPT_TITLE |
|---------|--------------|------------|
| 1200-02 | (null) | HR |
| 1200-05 | MARLOWE | FINANCE |
| 2955-03 | JOHNM | MARKETING |
假社会安全号码
(FAKE 名称只是提醒一下,这些都是随机生成的值。)虽然这通常是人事记录和数据库中流行的“unqiue”值,但根据美国社会保障局的说法,这个值不是独特的。这也是有问题的,因为最近通过了隐私法,该值及其转移受到严格监管。
名称组合
即使通过包含中间名首字母创建了额外的组合,不知何故,同名的人仍然太多。看看社会保障局对 2012 年出生婴儿的注册姓名的说法:
从现在起的二十年后,当 2012 年的 JACOB's 和 SOPHIA's 毕业时,他们将与成千上万像他们一样的人一起涌入职场…… p>
由于婚姻或法律原因导致的姓名更改也会威胁到数据库记录的参照完整性,因为数据库记录依赖于它们作为业务关键值的值。
部门编号
一些公司会尝试从其他值派生密钥以生成SMART KEYS。在实践中观察到这些类型的键根本不聪明。示例中的值:1200-02、1200-05、2955-03 旨在类似于“智能钥匙”。第一个值可能是公司园区或多地点业务的街道地址或建筑物编号。第二个值(“-02”、“-03”、“-05”)可能是部门所在建筑物的楼层。
更改建筑物、移动部门或完全搬迁业务将使DEPARTMENT ID 的这种位置依赖关系无用。
部门经理
这个很微妙,但在这种关系连接中有一个漏洞。 MANAGER 也是一个员工,这使得 EMPLOYEE 和 DEPARTMENT 之间的关系连接成为循环连接:
-
MANAGER(来自DEPARTMENT)是EMPLOYEE 表的外键约束,还是
-
DEPT_ID (FROM EMPLOYEE) 是 DEPARTMENT 表的外键约束吗?
如果您放弃 MANAGER 和 EMPLOYEE 上的某个键列(LAST_NAME 或 FIRST_NAME + LAST_NAME)之间的外键约束,您将面临MANAGER 的值不一致的风险。
...看着
Query of The DEPARTMENT Table:
| DEPT_ID | DEPT_MANAGER | DEPT_TITLE |
|---------|--------------|------------|
| 1200-02 | (null) | HR |
| 1200-05 | MARLOWE | FINANCE |
| 2955-03 | JOHNM | MARKETING |
DEPT_MANAGER 在DEPARTMENT 表中的错位,因为部门经理的姓名有三种不同的表示方式:无(空)、全大写姓氏、全大写名字、姓氏首字母.
结论
从这篇文章中吸取的一个重要教训是,通过集成派生值来使键更多而不是键,使值基于业务规则的假设会限制数据库设计的灵活性,因为如果业务规则发生变化,Primary Keys 或 Joining Key 值等值也会发生变化。
作为业务应用程序的开发人员或维护人员,如果您控制并拥有代表业务应用程序本身内部结构的部分,您(或您的团队)将能够更好地支持当前的业务条件。主键可能永远不会真正出现在客户或面向用户的情况下,但它应该受到保护,以便它所代表的关系不会随着时间而改变。
特别感谢:
来自 2012 年流行的婴儿名字页面的图片来源:
http://www.ssa.gov/OACT/babynames/#ht=0