Error about CASCADE in Sql - Server 2008 - sql-server

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.

Related

In the FK of the two tables, error to cycles or multiple cascade paths

enter image description here
The three tables have a FK relationship.
Post.PostBy is NOT NULL, Post.Category_id is Nullable.
An error has occurred.
Introducing FOREIGN KEY constraint 'FK_Post_Category' on table 'Post' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
ALTER TABLE [Category] ADD CONSTRAINT [FK_Category_CreatedBy] FOREIGN KEY ([CreatedBy])
REFERENCES [Account]([_id])
ON DELETE CASCADE
ALTER TABLE [Post] ADD CONSTRAINT [FK_Post_PostBy] FOREIGN KEY ([PostBy])
REFERENCES [Account]([_id])
ON DELETE CASCADE
ALTER TABLE [Post] ADD CONSTRAINT [FK_Post_Category_id] FOREIGN KEY ([Category_id])
REFERENCES [Category]([_id])
ON DELETE SET NULL
I don't understand.
PostBy is NOT NULL, so when the referenced row is deleted, we want it to be deleted along with it.
Category_id is NULLABLE, so if the reference row is deleted, set a NULL value.
Category and Post refer to Account, but I think it should work because they have different Account values.

On update cascade for a self-referencing key - SQL Server

I am trying to figure out how to perform on update cascade on a self-referencing temporal table using triggers. While I found that this post (On delete cascade for self-referencing table) is the closest it can get to my answer, I had the below questions:
The Answer and the question seems incomplete in the post. Can you please tell me what is contained in Deleted table in the post? What is id in Deleted table and Comments table? Is it a primary key? What if primary key is a pair of columns? Also, I am not sure why is IDs inside the CTE IDs. Seems incorrect. I am not sure.
What would the on update cascade specific trigger look like if the table has other foreign key constraints?
I have the below table setup. Can you please help me create a trigger for it on update cascade on the foreign key FK_Son_Height_Weight?
I could use a surrogate key here but there are several tables that have foreign key reference to PK_Height_Weight. Is there a way to make sure I dont need a surrogate key?
(Note: the table has been modified for privacy reasons)
CREATE TABLE no.Man (
Height varchar(100) NOT NULL,
Weight varchar(50) NOT NULL,
CONSTRAINT PK_Height_Weight PRIMARY KEY (Height, Weight),
CONSTRAINT FK_Weight FOREIGN KEY (Weight)
REFERENCES no.Human (Weight)
On Update Cascade,
Son_Height varchar (100) NOT NULL,
Son_Weight varchar (50) NOT NULL,
CONSTRAINT FK_Son_Height_Weight FOREIGN KEY (Son_Height, Son_Weight)
REFERENCES no.Man(Height,Weight)
On Update Cascade
)
Since the table is a temporal table, only 'After Update' trigger can be used on it and not the 'Instead Of Update' trigger (link for reference). I used the below solution for now to set stuff to null. This isnt a complete answer - yet trying to share with the community what I know.
CREATE or ALTER TRIGGER no.Weight_Height
ON no.Man
After UPDATE
AS
Set nocount on
IF ( UPDATE (Height) AND UPDATE (Weight) )
;With BA_DEL_Join as
(
select d.Height as d_Height, d.Weight as d_Weight,
d.Son_Height_Number as d_Son_Height_Num, d.Son_Weight as
d_Son_Weight, ba.Height as ba_Height, ba.Weight as ba_Weight,
ba.Son_Height_Number as ba_Son_Height_Num, ba.Son_Weight as
ba_Son_Weight
from deleted d
inner join no.Man ba
on d.Height = ba.Son_Height_Number and d.Weight = ba.Son_Weight
)
Update no.Man
set Son_Height_Number = NULL, Son_Weight = NULL
from BA_DEL_Join
where d_Height = ba_Son_Height_Num and d_Weight = ba_Son_Weight
Go
Even though this code mimics a cascading event - it does not enfore referential integrity.

SQL Server error: introducing foreign key constraint on table may cause cycles or multiple cascade paths

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.

Can't Create Foreign Key: May Cause Cycles

I've got a very simple relationship between two tables that are used to manage custom UI branding:
ui_portal_branding
CREATE TABLE ui_portal_branding
(
id VARBINARY(16) NOT NULL,
branding_type VARCHAR(128) NOT NULL,
portal_name NVARCHAR(128) NOT NULL,
theme_id VARBINARY(16) NOT NULL,
portal_logo VARBINARY(16) NULL,
portal_favicon VARBINARY(16) NULL,
background_color VARCHAR(50) NULL,
organization_id VARBINARY(16) NULL,
CONSTRAINT pk_ui_port_bran_id PRIMARY KEY (id)
)
ui_portal_resource
CREATE TABLE ui_portal_resource
(
id VARBINARY(16) NOT NULL,
mime_type NVARCHAR(128) NOT NULL,
binary_data VARBINARY(MAX) NOT NULL,
CONSTRAINT pk_ui_port_reso_id PRIMARY KEY (id)
)
Branding is the main table, Resources is a BLOB store for binary data. Both portal_logo and portal_favicon in the branding table are optional binary data from the resource table.
I'd like to define this as a foreign key constraint with the following general logic: neither logo or favicon are required to be defined. If they are defined, they point to a record in the resource table by ui_portal_resource.id. If the data is deleted from the resource table, I want to set the corresponding column in the branding table to null. I don't want to disallow the resource deletion, I don't want to cascade the delete to the branding table.
So I define the following:
ALTER TABLE ui_portal_branding
ADD CONSTRAINT fk_ui_port_bran2ui_port_reso
FOREIGN KEY (portal_logo) REFERENCES ui_portal_resource (id)
ON DELETE SET NULL
So far so good. Now I define:
ALTER TABLE ui_portal_branding
ADD CONSTRAINT fk_ui_port_bran2ui_port_reso2
FOREIGN KEY (portal_favicon) REFERENCES ui_portal_resource (id)
ON DELETE SET NULL
and all of a sudden we have a problem:
Introducing FOREIGN KEY constraint 'fk_ui_port_bran2ui_port_reso2' on table 'ui_portal_branding' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
This to me seems wrong. I'm not introducing a cycle. It's two tables with the foreign keys defined in a single direction. I guess it can technically be multiple cascade paths–if the same resource is the favicon and the logo it has to set 2 things null. But really? This is the deal breaker for the SQL Server engine? Oracle and Postgres both find this situation to be acceptable.
Is there a sensible workaround for this issue? I'm not interested in a solution involving triggers. Is there a better way to model the data? I was hoping that the resources table could service more than just the branding table, which led to the current FK placement. But maybe that is just not possible?

How to DELETE without ON DELETE CASCADE (conflict REFERENCE constraint)

I have a gigantic legacy database with a table that has multiple foreign keys pointing to one other table and with not a single cascade in sight, similar to sample tables below:
create table Users (
Id int primary key identity,
Name varchar(max)
)
create table Products (
Id int primary key identity,
Name varchar(max),
CreatedBy int foreign key references Users(Id),
UpdatedBy int foreign key references Users(Id)
)
insert into Users values('Bar')
insert into Users values('Baz')
insert into Products values('Foo', 1, 2)
I need to be able to to delete some of the old data, but it of course throws reference exceptions:
delete from Users where Name='Bar'
The DELETE statement conflicted with the REFERENCE constraint "FK__Products__Create__1AD3FDA4". The conflict occurred in database "Foo", table "dbo.Products", column 'CreatedBy'.
Due to the sheer complexity of the database I can't predelete all of the references, so I'm trying to add temporary foreign keys programmatically with cascades set to resolve them. However, for this particular table that has multiple foreign keys to one other table, this results in cycles or multiple cascade paths on the second UpdatedBy alter:
alter table Products add foreign key (CreatedBy) references Users(Id) on delete cascade
alter table Products add foreign key (UpdatedBy) references Users(Id) on delete cascade
Introducing FOREIGN KEY constraint 'FK__Products__Update__1DB06A4F' on table 'Products' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
How can I make delete from Users where work while maintaining referential integrity, either by somehow getting around multiple cascade path issues or otherwise?
Personally I would not do this (I would pre-delete all the referenced data and manually check the integrity). See: Can foreign key constraints be temporarily disabled using T-SQL?
Quote:
-- disable all constraints
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"
Delete your data once the constraints are disabled, but remember to turn them back on again afterwards!
-- enable all constraints
EXEC sp_msforeachtable #command1="print '?'", #command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
Also note that the stored procedure sp_msforeachtable is undocumented and may disappear in future releases of SQL Server.
If you'd rather not blanket-disable constraints (perhaps you have a list of the tables that apply) then simply disable them as you can see in the code above.
ALTER TABLE [Products] NOCHECK CONSTRAINT ALL
DELETE FROM [Users] where Name='Bar'
ALTER TABLE [Products] WITH CHECK CHECK CONSTRAINT ALL
All credit goes to kristof's answer. Please up vote!

Resources