MSSQL Constraint may cause cycles or multiple cascade paths [duplicate] - sql-server

This question already has answers here:
Foreign key constraint may cause cycles or multiple cascade paths?
(11 answers)
Closed 7 years ago.
I have a scenario like this:
User can own multiple Accounts. User also has bitcoin addresses, (which he inputs by himself) and they are "withdrawal addresses". Each Account also may have multiple bitcoin addresses (which are "deposit addresses").
All addresses are in one table, the only difference is that deposit/withdrawal are just specified by a column Type in table BitcoinAddresses.
I would like to create a scenario where deleting User will cause all the withdrawal BitcoinAddresses he owns to be deleted, and also all the Accounts he owns to be deleted. But deleting an Account should cause the BitcoinAddresses reference to be set to NULL.
I've tried something like that:
CREATE TABLE [dbo].[Users] (
[Id] NVARCHAR (128) NOT NULL,
[UserName] NVARCHAR (64) NULL,
CONSTRAINT [PK_dbo.Users] PRIMARY KEY CLUSTERED ([Id] ASC),
);
CREATE TABLE [dbo].[Accounts] (
[Id] BIGINT IDENTITY (1, 1) NOT NULL,
[UserId] NVARCHAR (128) NOT NULL,
[Number] BIGINT NOT NULL,
CONSTRAINT [PK_dbo.Accounts] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_dbo.Accounts.Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([Id]) ON DELETE CASCADE
);
CREATE TABLE [dbo].[BitcoinAddresses] (
[BitcoinAddressId] INT IDENTITY (1, 1) NOT NULL,
[Address] NVARCHAR (MAX) NOT NULL,
[AccountId] BIGINT NULL,
[UserId] NVARCHAR (128) NULL,
[Type] NVARCHAR (MAX) NULL,
CONSTRAINT [PK_dbo.BitcoinAddresses] PRIMARY KEY CLUSTERED ([BitcoinAddressId] ASC),
CONSTRAINT [FK_dbo.BitcoinAddresses_dbo.Accounts_AccountId] FOREIGN KEY ([AccountId]) REFERENCES [dbo].[Accounts] ([Id]) ON DELETE SET NULL,
CONSTRAINT [FK_dbo.BitcoinAddresses_dbo.Users_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[Users] ([Id]) ON DELETE CASCADE
);
This solution causes an error:
Introducing FOREIGN KEY constraint 'FK_dbo.BitcoinAddresses_dbo.Users_UserId' on table 'BitcoinAddresses' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
But obviously I don't see any cycles in this approach. Can you explain to me why this behaviour happens? How can I solve it? I would like to note, that I don't want to split Wihtdrawal and Deposit Addresses to two different tables (as this would be a correct solution for this scenario, but I want to know why I can't create such references)
Here's my fiddle to play with: http://sqlfiddle.com/#!6/5d9cd

If you delete a user, his accounts will get deleted and his bitcoinaddresses will get deleted. But when his account gets deleted, the account's bitcoinaddresses will also get updated to NULL. That's too complicated for SQL Server. It needs the cascade chains to be simple and neat and not branch and/or converge. How can SQL-Server know which you want if a user deletion would result in both the deletion of bitcoin and setting its account to NULL?

Related

Bare Sql Server - Introducing FOREIGN KEY constraint on table may cause cycles or multiple cascade paths

This is very similar to Introducing Foreign key Constraint on table may cause cycles or multiple cascade paths, except that the answer to that question does not explain the rationale behind the error.
I have the following simple schema:
CREATE TABLE [dbo].[DbInfo](
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY
)
GO
CREATE TABLE [dbo].[MyTable](
[Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
[DbInfo1Id] [int] NOT NULL,
[DbInfo2Id] [int] NOT NULL
)
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [FK_MyTable_DbInfo_DbInfo1Id] FOREIGN KEY([DbInfo1Id])
REFERENCES [dbo].[DbInfo] ([Id])
ON DELETE CASCADE
GO
Now I would like to add the same constraint to the column MyTable.DbInfo2Id:
ALTER TABLE [dbo].[MyTable] ADD CONSTRAINT [FK_MyTable_DbInfo_DbInfo2Id] FOREIGN KEY ([DbInfo2Id])
REFERENCES [DbInfo] ([Id])
ON DELETE CASCADE;
But I get the following error:
Introducing FOREIGN KEY constraint 'FK_MyTable_DbInfo_DbInfo2Id' on table 'MyTable' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
You can reproduce it in the Sql Fiddle
Why what I am doing here is problematic?
Because the CASCDE mode will drop ID that can possibly be use by the other constraints that will cause cascade too that will drop ID that can possibly be use by the primer constraints that will cause cascade too... an so on !

How to emulate ON UPDATE CASCADE for SQL Server with triggers

I have this SQL Server table which has a foreign key to itself that I use to store specific nodes in which tried to add the property ON UPDATE CASCADE for recursive updates that throws an error:
Introducing FOREIGN KEY constraint 'X' on table 'Type' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
CREATE TABLE [dbo].[Type]
(
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] VARCHAR(256) NOT NULL,
[Parent] VARCHAR(256) NULL,
PRIMARY KEY CLUSTERED ([Id] ASC),
UNIQUE NONCLUSTERED ([Name] ASC),
FOREIGN KEY ([Parent])
REFERENCES [dbo].[Type] ([Name]) ON UPDATE CASCADE
);
I know that there is a valid answer posted in another question but it's for delete only and this is not what I'm looking for and since I'm not really that good in SQL don't know how to implement something like this for update myself.
How could I implement something like this with triggers?

Shortcut to Assign Multiple Foreign Keys Using Keyword CONSTRAINT

Currently, I have the following code in my SQLQuery:
CREATE TABLE OrderTable (
OrderNumber varchar(3) NOT NULL,
Date_Time datetime NOT NULL,
WaitID varchar(7) NOT NULL,
CashID varchar(7),
TableNumber varchar(3) NOT NULL,
CONSTRAINT PK_Order PRIMARY KEY (OrderNumber, Date_Time),
CONSTRAINT FK_WaitID FOREIGN KEY (WaitID) REFERENCES WaiterWaitress(ID),
CONSTRAINT FK_CashID FOREIGN KEY (CashID) REFERENCES Cashier(ID),
CONSTRAINT FK_TableNumber FOREIGN KEY (TableNumber) REFERENCES RestTable(TableNumber)
);
I had to retype the CONSTRAINT ... FOREIGN KEY ... REFERENCES ... three times. Is there a shortcut to this while still maintaining the ability to name the foreign key (i.e. FK_WaitID)?
You could do some sort of complicated script after you run the CREATE TABLE statement to add the constraints without repeating the actual keyword "CONSTRAINT", but that code will not "look a bit better".
Writing it this way keeps it clear for others in the future who may need to review the structure. The constraints and keys are clearly laid out, and that's really the way it should be.

SQL Server - Two columns in child table referencing same column in parent table

As reported by the title I have a child table (Contracts) in which there are two columns, each of them referencing the same key column in the parent table (Clients).
The reason why I have made this design choice is that the parent table contains the clients but at the same time a client could be a provider company for another client.
The problem which I am encountering is that: the table are created correctly but the foreign keys (related only to these two tables) seems to be duplicated in both the child table (Contracts - the place where they should be stay) and in Clients (don't know why they are shown also here). I can see this duplicate when I open the SSMS relationship designer and I see in both tables the presence of the two foreign keys.
Here below the code which generate me this trouble (will be present other tables not mentioned here because them do not create issues):
Table Clients:
CREATE TABLE tblClients
(
VAT_Number NVARCHAR(30) NOT NULL PRIMARY KEY,
Country_EID NVARCHAR(5) NOT NULL,
User_EID NVARCHAR(50) NOT NULL,
Is_Company_Group BIT NOT NULL,
Recording_Date SMALLDATETIME NOT NULL
CONSTRAINT DF_tblClients_Recording_Date DEFAULT CONVERT(SMALLDATETIME, GETDATE()),
General_Notes NVARCHAR(300),
CONSTRAINT tblClients_Country_EID_FK
FOREIGN KEY (Country_EID) REFERENCES tblCountryLkp(Country_ID),
CONSTRAINT tblClients_User_EID_FK
FOREIGN KEY (User_EID) REFERENCES tblUsers(User_ID)
);
Table Contracts:
CREATE TABLE tblContracts
(
Contract_ID_Old NVARCHAR(30) NOT NULL,
Contract_ID_New NVARCHAR(15) NOT NULL,
EVAT_Client NVARCHAR(30) NOT NULL,
Billing_Type_EID INT NOT NULL,
User_EID NVARCHAR(50) NOT NULL,
Type_EID INT NOT NULL,
EVAT_Company NVARCHAR(30) NOT NULL,
Status_EID INT NOT NULL,
Recording_Date SMALLDATETIME NOT NULL
CONSTRAINT DF_tblContracts_Recording_Date DEFAULT CONVERT(SMALLDATETIME, GETDATE()),
PRIMARY KEY (Contract_ID_Old, Contract_ID_New),
CONSTRAINT tblContracts_Billing_Type_EID_FK
FOREIGN KEY (Billing_Type_EID) REFERENCES tblBillingTypeLkp(Billing_Type_ID),
CONSTRAINT tblContracts_User_EID_FK
FOREIGN KEY (User_EID) REFERENCES tblUsers(User_ID),
CONSTRAINT tblContracts_Type_EID_FK
FOREIGN KEY (Type_EID) REFERENCES tblContractTypeLkp(Contract_Type_ID),
CONSTRAINT tblContracts_Status_EID_FK
FOREIGN KEY (Status_EID) REFERENCES tblStatusLkp(Status_ID),
CONSTRAINT tblContracts_EVAT_Client_Company_FK
FOREIGN KEY (EVAT_Client) REFERENCES tblClients(VAT_Number),
CONSTRAINT tblContracts_EVAT_Company_FK
FOREIGN KEY (EVAT_Company) REFERENCES tblClients(VAT_Number)
);
Could someone help me to find the issue and to avoid that the duplication of the foreign keys related to EVAT_Client and EVAT_Company fields are created?
Thank you.
I am replying here to the question of KumarHarsh (since in the comments I didn't get to post images).
In the image will be present the screenshot of the table tblContracts where it could be seen the two foreign keys which, correctly, are defined for this table.
And the screenshot of the table tblClients where it could be seen the two same foreign keys which, in my opinion, are present incorrectly for the table tblClients.
I hope this helps to find the issue.
Thank you.

Can I have a foreign key in my table be null?

I have this DDL:
CREATE TABLE [dbo].[Test] (
[TestId] VARCHAR (20) NOT NULL,
[Title] NVARCHAR (100) NOT NULL,
[TopicId] INT NOT NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED ([TestId] ASC),
CONSTRAINT [FK_TestTopic] FOREIGN KEY ([TopicId]) REFERENCES [dbo].[Topic] ([TopicId])
);
I would like the allowed values of the TopicId to be null or one that matches the TopicId in the Topic table.
Can someone tell me how I can describe the foreign key for this?
Yes, foreign key constraint columns may allow NULLs. Simply change the foreign key column to allow NULL values. Referential integrity of NULL values are not checked. This is a common practice for optional (zero-or-more) relationships.
Well.. You could do that very easily just by making the field to allow null.. But, keep this in your mind, 'you are breaking data modelling'.

Resources