首先,我要说的是,我仍然是这个真实世界数据库中的菜鸟,我希望能够对这种情况有所了解。
我最近整理了一个基本的asp web应用程序来管理带有两个表的SQL数据库。表格如下:
密钥表:
KEY_ID Key_desc KEY_NUMBER Key_location 由...发出 EMP_ID
Emp表:
EMP_ID Emp_fname emp_lname的 Emp_phone
如您所见,这些表由emp_id字段链接。但是,如果未将密钥分配给员工,则密钥表允许emp_id列中的空值。
由于这种情况,我关注数据库中的整体关系,孤儿记录正成为一个问题。
由于密钥表允许该列为空值,这是否意味着它不在1NF中?
截至目前,Web应用程序通过选择emp_id为null的所有记录来从密钥表中提取所有记录来分配密钥,然后将emp_id分配给选定的密钥。
但是,只有当密钥具有关联的员工时,该关系才存在,并且似乎必须有更好的方法来执行此操作。
改变应用程序可能有点晚了,所以我或多或少都会因为纯粹的好奇而问这个问题。
我以为我可能需要一个已分配的密钥表和一个未分配的密钥表,但我不知道如何将它们与当前数据库字段链接起来。谁能给我一些建议呢?或者也许可以帮我找出一种更好的方法将数据库链接在一起?
我主要担心的是孤儿记录
这是在手机上输入的,如果有错误,请原谅我。
编辑:非常感谢那些对此作出回应的人。我得到了比我想象的更多的帮助。当我确定要采取的路线时,将在稍后标记答案。有人告诉我这是个合适的地方。
答案 0 :(得分:1)
另一种方法是创建第三个表,以记录键分配。如果未分配密钥,则不要在该表中放置一行。不要在密钥表中放入emp_id外键。
关于您在评论中提问的示例:
CREATE TABLE KeyAssignment (
key_id INT PRIMARY KEY,
emp_id INT NOT NULL,
FOREIGN KEY (key_id) REFERENCES keys (key_id),
FOREIGN KEY (emp_id) REFERENCES emp (emp_id)
);
不需要其他属性,因为密钥和员工的所有详细信息都已存储在其他表中。
请注意,上表并不是多对多表,因为key_id本身就是主键。每个key_id只能有一行(或零行)。如果给定key_id有一行,则emp_id为NOT NULL,因此必须进行赋值。未分配的密钥在此表中没有行(直到它们被分配)。
至于你的原始设计是否在1NF,是的,大多数人都同意它。非空Emp_id的值是来自员工域的单个值,这就是1NF所需的值。
SQL有一个额外的规则,即NULL可以被视为任何域的虚拟成员,尽管此规则是否与关系理论一致controversial。 C.J.Date认为SQL中NULL的概念与关系理论不相容。但是E.F. Codd认识到NULL的重要性,表示行的成员不适用或未知。
答案 1 :(得分:0)
我认为您正在寻找的数据库设计类似于以下内容(使用MySQL语法):
create table Emp(
Emp_ID int not null auto_increment PRIMARY KEY,
LastName varchar(30),
FirsName varchar(20),
Phone varchar(20)
);
create table `Key`(
Key_id int not null auto_increment PRIMARY KEY,
Description varchar(255),
Key_number int,
Key_location int, -- or your data type for this column
Issued_by int -- or your data type for this column
Emp_id int, -- foreign key to Emp table
FOREIGN KEY (Emp_id) references Emp(Emp_ID)
ON DELETE CASCADE -- or RESTRICT / NO ACTION options -- see notes below
);
还有三点:
1)您还可以使用RESTRICT / NO ACTION选项来防止删除主键行。
2)避免对表名或列名使用保留字,例如Key
。
3)我不希望使用表名前缀列名,例如。 emp_lname的。它是多余的,不太可读。
修改强> 根据@Hugh Jones,我将Issued_by和Emp_id列分开 - 谢谢Hugh