В дополнение к первичному ключу в таблице адресов (для Id) вы должны также объявить еще одно ключевое ограничение, ограничение UNIQUE, для (Id, UserId).
ALTER TABLE Address ADD CONSTRAINT UQ_Address_UserCheck UNIQUE (Id,UserID)
Затем вы можете либозамените ваши существующие FK с Order на address или добавьте дополнительные, которые проверяют оба столбца
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.