Reputation: 55
I have 3 tables and the schema setup is like this:
tenant object: tenant id, first name, last name, phone, email, apartment id
apartment object: apartment id, address, square footage, monthly utility fee, monthly parking fee, last cleaning date
contract object: contract id, apartment id, tenant id, start date, end date, monthly rent
Here is my script:
CREATE TABLE [dbo].[Contract]
(
[ContractId] INT IDENTITY (1, 1) NOT NULL,
[StartDate] DATETIME NULL,
[EndDate] DATETIME NULL,
[MonthlyRent] FLOAT NULL,
[AptId] INT NOT NULL,
[TenantId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([ContractId] ASC),
CONSTRAINT [FK_dbo.Contract_dbo.Apartment_AptId] FOREIGN KEY ([AptId])
REFERENCES [dbo].[Apartment] ([AptId]) ON DELETE CASCADE,
CONSTRAINT [FK_dbo.Contract_dbo.Tenant_TenantId] FOREIGN KEY ([TenantId])
REFERENCES [dbo].[Tenant] ([TenantId]) ON DELETE CASCADE
)
It complains when I am trying to add the foreign key constraint for the Apartment table. I know why it is because the Tenant Table already holds the Apartment foreign key constraint when I am trying to include it into the Contract table. But I still need to include the AptId column in the Contract table and populate it with the correct Ids. Is there a way to do that without having to do an inner join of sort?
Upvotes: 0
Views: 75
Reputation: 2608
The issue which you seem to be running into is a cyclical or circular reference.
On delete cascade will delete all references to the given record as a foreign key. Case in point, if you delete a record in the apartment table, all tenant records referencing that apartment will be deleted. The issue which you seem to have is that you will have two correct "paths" or ways in which a contract record can be deleted, and a third path which is causing the trouble:
Your question asks for a way to keep the FK in place (in terms of not requiring a join), without running into this issue. You can do that with the following modification to your create table script:
I commented out your apartment_id field and replaced it with an identical one albeit without the "on delete cascade" clause. Since that was the issue, you can still keep the FK without running into a circular reference.
CREATE TABLE [dbo].[Contract]
(
[ContractId] INT IDENTITY (1, 1) NOT NULL,
[StartDate] DATETIME NULL,
[EndDate] DATETIME NULL,
[MonthlyRent] FLOAT NULL,
[AptId] INT NOT NULL,
[TenantId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([ContractId] ASC),
/*CONSTRAINT [FK_dbo.Contract_dbo.Apartment_AptId] FOREIGN KEY ([AptId])
REFERENCES [dbo].[Apartment] ([AptId]) ON DELETE CASCADE,*/
CONSTRAINT [FK_dbo.Contract_dbo.Apartment_AptId] FOREIGN KEY ([AptId])
REFERENCES [dbo].[Apartment] ([AptId]),
CONSTRAINT [FK_dbo.Contract_dbo.Tenant_TenantId] FOREIGN KEY ([TenantId])
REFERENCES [dbo].[Tenant] ([TenantId]) ON DELETE CASCADE
)
Give it a run and it should work just fine for you.
Upvotes: 1