2014-09-12 71 views
1

我有一个与链接表的多对多关系,我需要正式规则集。以下是我的问题:表:两者都有复合(谢谢stakx纠正我)主键。我的问题是:复合主键和链接表规则

左(L)和右(R)(L & R)链接表有其自己的主键,但很明显,因为R表具有每个复合初选,链接表必须包含多个外键。没问题。即

L Table: 
LID  (int)  PK1 
LSomeDate (DateTime) PK2 
Other Fields... 

R Table: 
RID  (int)  PK1 
RSomeDate (DateTime) PK2 
Other Fields... 

Link Table: 
ID  (int)  PK 
LID  (int)  FK1 
LSomeDate (DateTime) FK1 
RID  (int)  FK2 
RSomeDate (DateTime) FK2 

要求1:任一表中的实体可以存在没有其他实体。因此,而不是1:M,我们应该在M:M的两侧都有一个0:M。我猜测(也许是错误的),这意味着我必须离开链接表外键空。但是如果我这样做,我可以输入LID并将LSomeDate字段留空。或相反亦然。同样与RID和RSomeDate。

我的第一个问题是,什么是创建一些“任何(规则,约束,默认,触发等)”的强制用户输入LID,如果输入LSomeDate或输入LSomeDate已输入LID。然后我可以将其应用于R FK。这将防止在FK的一部分留下空位。

本质上...... FK的整个L面都是空的,或者两个字段都被填充(一个有效的ref)。同样的R但这将是分开的。

我的另一个问题是......当创建链接表时,如果L表包含正确表的FKID,反之亦然,例如...如果上面的L表还包含RID和RSomeDate作为外​​键,反之亦然,或者它们在链接表中已经足够了。

在此先感谢。

+1

关于术语的注意事项:虽然表可以有多个候选键,但它们只能有一个主键。然而,这个主键可能是一个复合键(即,由多个列组成)。我假设你的意思是说你的L&R表都有一个复合主键? – stakx 2014-09-12 11:26:43

+0

@stakx - 我做了,并更新了问题。谢谢。 :) – 2014-09-12 11:31:04

+1

你说什么意思,_“...强制用户输入... ID”_?用户是否直接插入数据库?也就是说,您是想直接在数据库级别还是在应用程序级别执行此规则? – stakx 2014-09-12 11:35:31

回答

1

在链接表中输入条目的唯一原因是将一个L记录链接到另一个R记录。如果一个L存在而没有链接到任何R,那么在L中有一个recird,但是在链接表中没有这个特定的L和R组合的入口。

也就是说,只有在关联L和R时,N:N链接表中的条目才存在。也就是说,如果两个记录L和R没有链接(“一个没有另一个存在”),那么在链接表中根本就没有条目。因此,链接表中甚至不需要NULL值。

含义,理想情况下,所有链接表列都被声明为NOT NULL;突然你的问题消失了!

(这顺便说一句无关,与你的主键是复合材料;同一事实将保持非复合键)

如果,尽管如此,还是想声明这些列NULL能,并且你想在数据库层面确保例如在您的链接表L个外键没有被部分NULL,你可以添加一个CHECK约束:

ALTER TABLE LinkTable 
ADD CONSTRAINT CK_LinkTable_LID_LSomeDate 
CHECK ((LID IS NULL  AND LSomeDate IS NULL ) 
    OR (LID IS NOT NULL AND LSomeDate IS NOT NULL)) 

但同样,这将是无限美好的,如果所有的外键列的是NOT NULL能够摆在首位,因为这就是应如何设计N:N链接表。

+0

这非常有意义......我现在感觉像个假人。抱歉。我的脑袋有雾,因为我有多个地方发生这种情况,我试图理解它,因为它是由过去的开发者完成的。感谢您的帮助。 – 2014-09-12 11:45:03

+1

@FrancisRodgers:不用担心,交配。我们都在这里学习。 (如果您觉得它有帮助,请随时注册或接受答案;;) – stakx 2014-09-12 11:48:30

+0

因此,如果我理解正确。忘记约束,只是不允许链接表中的FK为空。这是因为0:N可以通过简单地在相关端输入记录而不通过链接表将0与N进行关联。链接表只有在将一方链接到另一方时才需要......这是正确的吗? – 2014-09-12 11:48:35