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?
Related
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 !
I have two tables, User and Data. For audit purposes, I have two columns added in the Datatable:AddedByandLastModifiedBy`.
Both columns reference the User table and its UserId column. I have a On delete set null constraint set on both the foreign keys. SQL Server does not let me create the table Data and throws the error:
Introducing FOREIGN KEY constraint 'FK__Data__LastModifi__0A9D95DB' on table 'Data' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
These are the SQL scripts:
CREATE TABLE [User]
(
UserId int PRIMARY KEY IDENTITY(1,1),
Name varchar(100) not null
)
CREATE TABLE [Data]
(
Id int PRIMARY KEY IDENTITY(1,1),
A int,
B varchar(10),
AddedBy int
FOREIGN KEY REFERENCES [User](UserId)
ON DELETE SET NULL,
LastModifiedBy int
FOREIGN KEY REFERENCES [User](UserId)
ON DELETE SET NULL
)
Removing the ON DELETE constraint solves the problem, but the question why can't I have two ON DELETE SET NULL conditions?
why can't I have two ON DELETE SET NULL conditions?
Because that would cause multiple cascade paths, and SQL Server simply doesn't support that.
There's an outstanding feedback request for this and to allow cascading in parent-child relationships here.
As a workaround you can either make one of the relationships ON DELETE NO ACTION, or use an INSTEAD OF DELETE trigger on USER that handles the cascading behavior.
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?
I have two tables:
CREATE TABLE [dbo].[AdminTest] (
[AdminTestId] INT IDENTITY (1, 1) NOT NULL,
[Title] NVARCHAR (100) NOT NULL,
CONSTRAINT [PK_AdminTest] PRIMARY KEY CLUSTERED ([AdminTestId] ASC)
);
GO
CREATE NONCLUSTERED INDEX [Test_ExamId_IX]
ON [dbo].[AdminTest]([ExamId] ASC);
CREATE TABLE [dbo].[AdminTestQuestion] (
[AdminTestQuestionId] INT IDENTITY (1, 1) NOT NULL,
[AdminTestId] INT NOT NULL,
[QuestionUId] UNIQUEIDENTIFIER NOT NULL,
CONSTRAINT [PK_AdminTestQuestion] PRIMARY KEY CLUSTERED ([AdminTestQuestionId] ASC),
CONSTRAINT [FK_AdminTestQuestionAdminTestId] FOREIGN KEY ([AdminTestId]) REFERENCES [dbo].[AdminTest] ([AdminTestId])
);
GO
CREATE NONCLUSTERED INDEX [AdminTestQuestion_AdminTestId_IX]
ON [dbo].[AdminTestQuestion]([AdminTestId] ASC);
Is there some way that I can change the definition of the tables so that when I delete a row from AdminTest then all the child rows in AdminTestQuestions for that test are deleted?
You can add ON DELETE CASCADE to your foreign key constraint;
CONSTRAINT [FK_AdminTestQuestionAdminTestId]
FOREIGN KEY ([AdminTestId]) REFERENCES [dbo].[AdminTest] ([AdminTestId])
ON DELETE CASCADE
An SQLfiddle to test with.
I may not need to point out that this is not necessarily a good idea in the long run, since it will make implicit changes to your data that other users may not know about. Use with caution.
I posted this problem yesterday and didn't get answer.
I attach here sample of my problem. I want to create this DB:
CREATE DATABASE [TRYShemen];
GO
USE [TRYShemen]
GO
CREATE TABLE Persons(
ID VARCHAR(50) PRIMARY KEY,
FullName VARCHAR(50) NOT NULL
);
CREATE TABLE Class(
ClassNum VARCHAR(30) PRIMARY KEY,
Teacher VARCHAR(50) NOT NULL,
constraint Class_FK foreign key (Teacher) references Persons (ID) ON DELETE NO ACTION ON UPDATE CASCADE,
);
CREATE TABLE Students(
StudentID VARCHAR(50) ,
ClassNum VARCHAR(30)
constraint Students_PK PRIMARY KEY (StudentID, ClassNum),
constraint Students_FK foreign key (StudentID) references Persons(ID) ON DELETE NO ACTION ON UPDATE CASCADE ,
constraint Students_FK1 foreign key (ClassNum) references Class(ClassNum) ON DELETE NO ACTION ON UPDATE CASCADE
);
and I get an error:
Introducing FOREIGN KEY constraint 'Students_FK1' on table 'Students' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
I know that if i change the 'Students_FK1' to ON CASCADE NO ACTION, it will work, but it's not my target. I want that if the id of 'Person' will update , it will update in the Students table too.
how can I solve it?
Thank You!!
So what can you do about it?
Consider this structure as an alternative.
table-Persons
table-Students
table-Teachers
table-Classes
table-Classes_to_Teachers
table-Classes_to_Students
Then you can have Cascading references for
Persons-->Students & Students-->Classes_to_Students
Persons-->Teachers & Teachers-->Classes_to_Teachers
When you access your data, you will have more joins to get all the data for one class.
But the constraints should work out.
Note that it says "may cause cycles or multiple cascade paths." If you follow a delete action through your ER diagram, you'll probably find that the delete action cascades to the same table via multiple routes.
In this case, imagine that the same person is both the teacher and the student in a class. Yes, I know, that's a logic error, but if that condition were true, then an update to that person would cascade to the students table via two routes.