I have a SQL statement that should add me some constraints. In that statement I want to set on two constraints two referential integrity conditions.
Here is my statement:
ALTER TABLE Vertraege
ADD CONSTRAINT FK_Kunde_Vertraege FOREIGN KEY(K_ID)
REFERENCES Kunde(K_ID),
CONSTRAINT FK_Standort_Vertraege FOREIGN KEY(S_ID)
REFERENCES Standort(S_ID) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT FK_Mitarbeiter_Vertraege FOREIGN KEY(M_ID)
REFERENCES Mitarbeiter(M_ID) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT FK_Dienstleistung_Vertraege FOREIGN KEY(D_ID)
REFERENCES Dienstleistung(D_ID),
CONSTRAINT FK_Compliance_Vertraege FOREIGN KEY(C_ID)
REFERENCES Compliance(C_ID);
So the problem ist, that I get an error because of this.
Notification 1785, level 16, status 0, line 28
Introducing FOREIGN KEY constraint 'FK_Mitarbeiter_Vertraege' on table 'vertreage' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Notification 1750, level 16, status 1, line 28
Could not create constraint or index. See previous errors.
Is it possible to set multiple referential integrity conditions and if not, how can I make multiple of them in SQL? Something like ALTER CONSTRAINT...
EDIT
Brian asked for this. On my table mitarbeiter I have following constraints. The strange thing is, they work
ALTER TABLE Mitarbeiter
ADD CONSTRAINT FK_Adresse_Mitarbeiter FOREIGN KEY(AD_ID)
REFERENCES Adresse(AD_ID) ON UPDATE CASCADE,
CONSTRAINT FK_Standort_Mitarbeiter FOREIGN KEY(S_ID)
REFERENCES Standort(S_ID) ON UPDATE CASCADE,
CONSTRAINT FK_Abteilung_Mitarbeiter FOREIGN KEY(AB_ID)
REFERENCES Abteilung(AB_ID) ON UPDATE CASCADE;
The error message mentions "multiple cascade paths", and with the additional constraints that you added to your question, my first suspicion that there is an interaction between the following items (edited from your initial post):
ALTER TABLE Vertraege
CONSTRAINT FK_Standort_Vertraege FOREIGN KEY(S_ID)
REFERENCES Standort(S_ID) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT FK_Mitarbeiter_Vertraege FOREIGN KEY(M_ID)
REFERENCES Mitarbeiter(M_ID) ON UPDATE CASCADE ON DELETE CASCADE,
and
ALTER TABLE Mitarbeiter
CONSTRAINT FK_Standort_Mitarbeiter FOREIGN KEY(S_ID)
REFERENCES Standort(S_ID) ON UPDATE CASCADE,
So you've got a constraint that goes directly from Vertraege to Standort, and another that goes from Vertraege through Mitarbeiter to Standort. My first suggestion would be to remove FK_Standort_Vertraege and see if that fixes your issue.
This is a guess, since the question does not include all the related tables.
You are trying to create a foreign key constraint from the table Vertraege to the table Mitarbeiter. It seems, however, there's already another [reverse] foreign key constraint (not shown) from the table Mitarbeiter to the table Vertraege. I can't be sure since you don't include the definition of the table Mitarbeiter.
SQL Server considers this a "cyclic relationship". This is all "legal", however. Nothing wrong with it. Well... as long as some of them are nullable, or they can be deferrable (but SQL Server does not implement the latter). The cyclic relationship may not only involve two tables, but also three or more. It's not clear from the question how many tables are involved, however.
The problem stems from the "cascade delete/update" rules you want to specify. This rules can possibly lead to massive data deletion or updating by a simple innocuous DELETE or UPDATE, such as:
delete from Vertraege where ID = 123
This statement seems to be deleting a single row. However, your cascade deletion rule can end up deleting thousands of rows from multiple tables at once without further confirmation. Is that what you want?
In any case, SQL Server doesn't like those cyclic cascade deletes/updates, since it considers them [justifiable] dangerous, and decides not to allow them.
Related
I have a database design like below. I have 3 tables Compartment, CompartmentRelation and CompartmentRelationType . CompartmentRelation table keeps the other compartments around the selected compartment (below,above,behind,infront,etc). CompartmentRelationType keeps the position. Think that i have compartments in the Compartment table named comp-1, comp-2, comp-3, comp-4 and insert the the compartments above comp-1 as comp-2,comp-3 in CompartmentRelation as below. Problem is that setting delete action as cascade for the column RelatedCompId in CompartmentRelation table throw the excaption as
Unable to create relationship 'FK_CompartmentRelation_Compartment1'.
Introducing FOREIGN KEY constraint 'FK_CompartmentRelation_Compartment1' on table 'CompartmentRelation' 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.
Which way should i follow ?
Compartment
comp-1
comp-2
comp-3
comp-4
Compartment Relation
comp-1 -> comp-2
comp-1 -> comp-3
CREATE TABLE [dbo].[Compartment] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (500) NOT NULL,
CONSTRAINT [PK_Compartment] PRIMARY KEY CLUSTERED ([Id] ASC),
CREATE TABLE [dbo].[CompartmentRelation] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[CompId] INT NOT NULL,
[RelationTypeId] INT NOT NULL,
[RelatedCompId] INT NOT NULL,
CONSTRAINT [PK_CompartmentRelation] PRIMARY KEY CLUSTERED ([Id] ASC),
CONSTRAINT [FK_CompartmentRelation_CompartmentRelationType] FOREIGN KEY ([RelationTypeId]) REFERENCES [dbo].[CompartmentRelationType] ([Id]) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT [FK_CompartmentRelation_Compartment1] FOREIGN KEY ([RelatedCompId]) REFERENCES [dbo].[Compartment] ([Id]),
CONSTRAINT [FK_CompartmentRelation_Compartment] FOREIGN KEY ([CompId]) REFERENCES [dbo].[Compartment] ([Id]) ON DELETE CASCADE ON UPDATE CASCADE);
CREATE TABLE [dbo].[CompartmentRelationType] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[Name] NVARCHAR (200) NOT NULL,
[NameLan1] NVARCHAR (200) NOT NULL,
[NameLan2] NVARCHAR (200) NULL,
CONSTRAINT [PK_CompartmentRelationType] PRIMARY KEY CLUSTERED ([Id] ASC)
);
Problem is that setting delete action as cascade for the column
RelatedCompId in CompartmentRelation table throw the excaption as
Unable to create relationship
'FK_CompartmentRelation_Compartment1'. Introducing FOREIGN KEY
constraint 'FK_CompartmentRelation_Compartment1' on table
'CompartmentRelation' 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.
The basic issue appears to be that deletes from table Compartment (and updates to its PKs) can cascade to CompartmentRelation through two different foreign keys. If you intend to support Compartments being related to themselves, then that's end-of-story for cascading from Compartment to CompartmentRelation -- you can't do it.* If you intend to forbid self relationships then you could try adding a check constraint to CompartmentRelation to enforce that prohibition, though I'm not at all sure that SQL Server will take that into account.
If SQL Server won't accept the cascading deletes then you have at least three options:
Make it an application responsibility to clean up compartment relationships before deleting compartments. (And don't cascade.)
Create triggers to handle relationship deletion when compartments are deleted. (And don't cascade.)
Create a stored procedure for deleting compartments, and make it handle the needed relationship deletions. (And don't cascade.)
Which way should i follow ?
Whichever of those makes the most sense for your application. All have advantages and disadvantages.
Additionally,
Do not cascade updates of surrogate key columns, especially when the key values are machine generated, as all yours are. Those keys should never be updated in the first place, and if an attempt were ever made to update one then it would be better for the DB to reject it, for whatever reason, than to accept it.
You probably don't want to cascade deletions of CompartmentRelationType to ComponentRelation. Including such cascading allows for deleting all the relations of a given type by deleting the type itself, but such a cascade is more likely to be performed mistakenly than intentionally, and if it were performed mistakenly then the resulting data loss would be significant. It's probably better to make the application delete all those relations explicitly if that's what it really means to do, and otherwise to reject deletion of types that are in use by existing relations.
*Technically, you could do it by cascading from only one of the two FKs with Compartment, but it seems unlikely that such a half-measure would serve your purposes.
I have a table in SQLite with specified FK as follows:
CONSTRAINT "model" FOREIGN KEY("category_id") REFERENCES "category"("id") deferrable initially deferred and I need to add ON DELETE CASCADE. I know that in SQLite you can't add constraint with ALTER so how can I combine these 2 constraints when creating a new table?
In the CREATE statement of the new table use:
CONSTRAINT model FOREIGN KEY(category_id) REFERENCES category(id)
ON DELETE CASCADE
DEFERRABLE INITIALLY DEFERRED
See the demo.
I have a task:
If a "shop" is deleted all references to it is set to NULL.
When I try to create a table:
CREATE TABLE TEST
(
id int Primary Key,
shop int FOREIGN KEY REFERENCES TEST(id) ON DELETE SET NULL,
);
I get an error:
Introducing FOREIGN KEY constraint 'FK__TEST__shop__2882FE7D' on table 'TEST' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Msg 1750, Level 16, State 0, Line 1
What am I doing wrong?
You are getting an error because you are creating a table with a reference to itself. This is not a good idea, and also this is not what you want.
For your task, you need to create another table, with a relationship (a foreign key) that references your first table. The foreign key must be defined properly to hold the rule that sets the child to NULL when the parent is deleted, like :
CONSTRAINT fk_name
FOREIGN KEY (child_col)
REFERENCES parent_table (parent_col)
ON DELETE SET NULL
See this link on how to set option ON DELETE in a foreign key
You can do this, but not exactly as you wish. The following works:
CREATE TABLE TEST (
id int Primary Key,
shop int,
FOREIGN KEY (shop) REFERENCES TEST(id) ON DELETE NO ACTION,
);
To be honest, I'm not sure why the in-line definition doesn't work. The more important point is the action. The SET NULL is not allowed, because SQL Server is very cautious about potential cycles. However, NO ACTION is allowed.
I have three tables as follows -
But when I add the foreign key reference, the relation is ( a straight line in the Database Diagram) not shown.
Following is the reference I wrote.
ALTER TABLE [dbo].EmployeeDesignation
ADD CONSTRAINT FK_EmployeeDesignation_Employee FOREIGN KEY (EmployeeId)
REFERENCES Employee (EmployeeId)
ON DELETE CASCADE
ON UPDATE CASCADE
;
ALTER TABLE [dbo].[EmployeeDesignation]
ADD CONSTRAINT FK_EmployeeDesignation_Designation FOREIGN KEY (DesignationId)
REFERENCES Designation (DesignationId)
ON DELETE CASCADE
ON UPDATE CASCADE
;
In addition, When I add another two tables (Department and EmployeeDepartment) I can see the relation in the diagram
The code for the reference is as follows --
ALTER TABLE [dbo].EmployeeDepartment
ADD CONSTRAINT FK_EmployeeDepartment_Department FOREIGN KEY (DepartmentId)
REFERENCES Department (DepartmentId)
ON DELETE CASCADE
ON UPDATE CASCADE
;
ALTER TABLE [dbo].EmployeeDepartment
ADD CONSTRAINT FK_EmployeeDepartment_Employee FOREIGN KEY (EmployeeId)
REFERENCES Employee (EmployeeId)
ON DELETE CASCADE
ON UPDATE CASCADE
;
What might be the reason That the later one showing relation line while the previous one is not showing?
Am I missing something?
Thanks !
Try closing SSMS and then reopening it again. Seems like the cache used by SSMS for some of functionality is not refreshed even upon closing and re-opening the database connection. check https://stackoverflow.com/a/4316415/364084
I've checked that none of the two tables has any foreign keys. I've checked that they both have Id of type uniqueidentifier. I runt the script and get this eror.
ALTER TABLE [dbo].[Records]
ADD CONSTRAINT [FK_dbo.Records_dbo.Users_UserId]
FOREIGN KEY ([UserId])
REFERENCES [dbo].[Users] ([Id])
--ON DELETE CASCADE
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_dbo.Records_dbo.Users_UserId". The conflict occurred in database "MyDb", table "dbo.Users", column 'Id'.
Not sure how to troubleshoot it... Tested both with and without the cascade...
It must be something to do with the existing data. There must be some records conflicting the foreign key creation. Try to create the key on an empty schema to see if it works. Use WITH NOCHECK to not to check existing rows at the time of foreign key creation, if you need that data.
Most likely you have a UserId in the Records table that does not exist in the Users table. This will certainly happen if you've been using 0 or some other value as a "default" value.