我有三个表,Customer
,PhoneNumber
和PhoneCall
。
PhoneNumber
包含电话号码,每个电话号码都属于客户。
PhoneCall
包含呼叫记录,并引用呼叫客户以及被呼叫的电话号码。
我想创建一个约束,阻止条目进入PhoneCall
表,其中引用的PhoneNumber
不属于引用的Customer
。
以下是我的表格:
Customer
Id
Name
PhoneNumber
Id
CustomerId (fk to Customer.Id)
AreaCode
Number
PhoneCall
CustomerId (fk to Customer.Id)
PhoneNumberId (fk to PhoneNumber.Id)
Description
Duration
客户和电话号码示例:
Customers = [
{ Id: 1, Name: 'Bob' },
{ Id: 2, Name: 'Richard' },
];
PhoneNumbers = [
{ Id: 1, CustomerId: 1, AreaCode: 'xxx', Number: 'xxxx' },
{ Id: 2, CustomerId: 2, AreaCode: 'yyy', Number: 'yyyy' }
];
我想阻止这样的条目:
PhoneCall = {
CustomerId: 1,
PhoneNumber: 2,
Description: 'call to customer',
Duration: 5
}
这似乎应该很容易通过约束来解决,但我真的很难弄清楚应该怎么做。是否有一种约束来解决这个问题?
感谢Kentaro的回答。
我最喜欢这个意思是,如果没有指定电话号码,我可以将PhoneNumberId
的电话记录设置为空。
这是我用来添加约束的查询
ALTER TABLE [PhoneNumbers] ADD UNIQUE ([Id], [CustomerId]);
ALTER TABLE [dbo].[PhoneCalls] ADD CONSTRAINT [FK_dbo.PhoneCalls_dbo.ReferencedPhoneNumberMustBelongToReferencedCustomer] FOREIGN KEY([PhoneNumberId], [CustomerId]) REFERENCES [dbo].[PhoneNumbers] ([Id], [CustomerId]);
答案 0 :(得分:3)
我认为对您的问题最简单的解决方案是:不要在CustomerId
表格中包含PhoneCall
。通过PhoneNumbers
表格查找。
只有一个客户ID,就不会发生冲突。
在PhoneNumbers(CustomerId, PhoneNumber)
上构建冗余唯一索引的另一种可能性。然后使用此索引作为外键引用。它将要求客户ID匹配。
答案 1 :(得分:1)
外键约束可以轻松地管理它(您已经将其作为标记)。您所要做的就是稍微更改PhoneCall表中的表定义和外键引用,以便它将引用PhoneNumber表中的CustomerID。但是为了做到这一点,你必须稍微改变PhoneNumber和PhoneCall的表定义,因为外键需要是引用表中的主键或候选键(即唯一的)。因此,使用提供的表定义,在TSQL中重新创建这些表将看起来像这样(假设数据类型)。
CREATE TABLE PhoneNumber(
Id INT UNIQUE,
CustomerId INT UNIQUE REFERENCES Customer(ID),
AreaCode INT(3),
Number INT(7),
CONSTRAINT CK_PhoneID_CustID (ID, CustomerID));
CREATE TABLE PhoneCall (
CustomerId INT REFERENCES Phonenumber(CustomerID),
PhoneNumberId INT REFERENCES PhoneNumber(Id),
Description NVARCHAR(MAX),
Duration INT);