除了地址表(在Id上)中的主鍵,您還應該在(Id,UserId)上聲明另一個關鍵約束,UNIQUE約束。
ALTER TABLE Address ADD CONSTRAINT UQ_Address_UserCheck UNIQUE (Id,UserID)
然後,您可以從訂單處理,或添加更多的,是檢查兩列替換現有FKS
ALTER TABLE Order ADD CONSTRAINT
FK_Order_DeliveryAddress_UserCheck FOREIGN KEY (DeliveryAddressID,UserID)
references Address (Id,UserId)
正如我說的,你可以添加這些都作爲附加的約束,如果你想要。
所以,稍作命名的調整,你的表都呈現爲這樣:
create table Users (
UserID int IDENTITY(1,1) not null,
Name varchar(30) not null,
/* Other columns */
constraint PK_Users PRIMARY KEY (UserID),
constraint UQ_User_Names UNIQUE (Name)
)
go
create table Addresses (
AddressID int IDENTITY(1,1) not null,
UserID int not null,
Street varchar(35) not null,
/* Other columns */
constraint PK_Addresses PRIMARY KEY (AddressID),
constraint FK_Addresses_Users FOREIGN KEY (UserID) references Users (UserID),
constraint UQ_Addresses_UserCheck UNIQUE (UserID,AddressID)
)
go
create table Orders (
OrderID int IDENTITY (1,1) not null,
UserID int not null,
DeliveryAddressID int not null,
BillingAddressID int not null,
/* Other columns - there may be other nullability concerns above */
constraint PK_Orders PRIMARY KEY (OrderID),
constraint FK_Orders_Users FOREIGN KEY (UserID) references Users (UserID),
constraint FK_Orders_DeliveryAddresses FOREIGN KEY (DeliveryAddressID) references Addresses (AddressID),
constraint FK_Orders_BillingAddresses FOREIGN KEY (BillingAddressID) references Addresses (AddressID),
/* Further constraints - ensure UserID -> AddressID match */
constraint FK_Orders_DeliveryAddress_UserCheck FOREIGN KEY (UserID,DeliveryAddressID) references Addresses (UserID,AddressID),
constraint FK_Orders_BillingAddress_UserCheck FOREIGN KEY (UserID,BillingAddressID) references Addresses (UserID,AddressID)
)
並與一些刀片應該努力嘗試它我們,除了最後(其中有一個用戶/地址不匹配),它的工作原理:
declare @UID1 int
declare @UID2 int
declare @AID1_1 int
declare @AID1_2 int
declare @AID2_1 int
declare @AID2_2 int
insert into Users (Name)
select 'User1'
set @UID1 = SCOPE_IDENTITY()
insert into Users (Name)
select 'User2'
set @UID2 = SCOPE_IDENTITY()
insert into Addresses (UserID,Street)
select @UID1,'Street1'
set @AID1_1 = SCOPE_IDENTITY()
insert into Addresses (UserID,Street)
select @UID1,'Street2'
set @AID1_2 = SCOPE_IDENTITY()
insert into Addresses (UserID,Street)
select @UID2,'Street1'
set @AID2_1 = SCOPE_IDENTITY()
insert into Addresses (UserID,Street)
select @UID2,'Street2'
set @AID2_2 = SCOPE_IDENTITY()
insert into Orders (UserID,DeliveryAddressID,BillingAddressID)
select @UID1,@AID1_1,@AID1_2 union all
select @UID2,@AID2_1,@AID2_1
insert into Orders (UserID,DeliveryAddressID,BillingAddressID)
select @UID1,@AID1_1,@AID2_1
結果:
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(1 row(s) affected)
(2 row(s) affected)
Msg 547, Level 16, State 0, Line 31
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_Orders_BillingAddress_UserCheck". The conflict occurred in database "Test", table "dbo.Addresses".
The statement has been terminated.
您應該在插入之前檢查所有發送的數據。您可以在ddbb結構中設置插入時所需的字段,但您應該始終在數據服務器端檢查ddbb之前檢查它們。 – Chumillas 2011-05-26 16:01:05
謝謝 - 我可以並且會這麼做 - 但是如果可以的話,我仍然希望在數據庫中設置一個檢查 - 因爲數據庫最終在參考完整性方面「最終停止」。 – Stuart 2011-05-26 16:04:07
在數據庫中檢查這種情況的唯一方法是在該表中檢查完整性的ON INSERT觸發器。 [HowTo](http://msdn.microsoft.com/en-us/library/ee336242.aspx) – Chumillas 2011-05-26 16:06:01