SQL Cycles or Multiple Cascade Paths - sql

I am having a problem with cycles. I am developing inventory system for IT department.
I am having problem with 3 tables.
INVENTORY table that is used to keep history of user actions and SOFTWARE and HARDWARE tables are used for storing inventory.
I would like to keep a single inventoryID that is unique for SOFTWARE and HARDWARE tables and when I use ON CASCADE DELETE I get an error:
Msg 1785, Level 16, State 0, Line 1
Introducing FOREIGN KEY constraint 'fk_inventory_inventoryIDhw' on table 'inventory' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Here are my tables. Could anyone help me out? How can fix the issue. Can't find right solution on the web. Thanks
CREATE TABLE inventory
(
statusID int,
inventoryStatus nvarchar(15),
inventoryID int,
userName nvarchar(15),
dates datetime2,
inventoryAction nvarchar(10),
categoryID int,
CONSTRAINT pk_inventory_statusID PRIMARY KEY(statusID),
CONSTRAINT fk_inventory_inventoryIDsw FOREIGN KEY(inventoryID) REFERENCES software(inventoryID) ON DELETE CASCADE,
CONSTRAINT fk_inventory_inventoryIDhw FOREIGN KEY(inventoryID) REFERENCES hardware(inventoryID) ON DELETE CASCADE,
CONSTRAINT fk_inventory_userName FOREIGN KEY(userName) REFERENCES users(userName) ON DELETE CASCADE
)
GO
CREATE TABLE hardware
(
inventoryID int,
hardwareID int,
partNumber nvarchar(15),
serial nvarchar(50),
price float,
supportID int,
manufacturerID int,
categoryID int,
description nvarchar,
deviceTypeID int,
CONSTRAINT pk_hardware_inventoryID PRIMARY KEY(inventoryID),
CONSTRAINT fk_hardware_categoryID FOREIGN KEY(categoryID) REFERENCES category(categoryID) ON DELETE CASCADE,
CONSTRAINT fk_hardware_supportID FOREIGN KEY(supportID) REFERENCES support(supportID) ON DELETE CASCADE,
CONSTRAINT fk_hardware_deviceTypeID FOREIGN KEY(deviceTypeID) REFERENCES deviceType(deviceTypeID) ON DELETE CASCADE,
CONSTRAINT fk_hardware_manufacturerID FOREIGN KEY(manufacturerID) REFERENCES manufacturer(manufacturerID) ON DELETE CASCADE,
)
GO
CREATE TABLE software
(
inventoryID int,
softwareID int,
version nvarchar(10),
name nvarchar(50),
license nvarchar(50),
price float,
supportID int,
categoryID int,
manufacturerID int,
programTypeID int,
description nvarchar,
CONSTRAINT pk_software_inventoryID PRIMARY KEY(inventoryID),
CONSTRAINT fk_software_categoryID FOREIGN KEY(categoryID) REFERENCES category(categoryID) ON DELETE CASCADE,
CONSTRAINT fk_software_supportID FOREIGN KEY(supportID) REFERENCES support(supportID) ON DELETE CASCADE,
CONSTRAINT fk_software_programTypeID FOREIGN KEY(programTypeID) REFERENCES programType(programTypeID) ON DELETE CASCADE,
CONSTRAINT fk_software_manufacturerID FOREIGN KEY(manufacturerID) REFERENCES manufacturer(manufacturerID) ON DELETE CASCADE
)
GO

As far as I can remember multiple fk constraints on the same column associated with more than one parent table is not workable. You might need another table to maintain this relationship. Please see: http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=173589

Having the same column as part of multipe Foriegn Key Constraints associated with multiple parent tables create referential integrity issues.
The best approach would be to normalise the design and introduce an intermediate table to retain the relation as 2 (or more) relations.

Related

Foreign key references mutiple columns in the database

When I get my EER converted to the relational schema I got this table which has a composite primary key like following,
CREATE TABLE branch
(
branch_number varchar(20),
b_code varchar(20),
name varchar(20),
address varchar(20),
--CONSTRAINTS
CONSTRAINT pk_branch PRIMARY KEY(branch_number,b_code),
CONSTRAINT fk_branch FOREIGN KEY(b_code) REFERENCES bank(b_code)
)
This above table is a weak entity and therefore it's having a key combination as a primary key. (due to the identifying relationship)
Then this branch table is in a one-to-many relation with the following table
CREATE TABLE account
(
account_no varchar(20),
balance float,
branch_number varchar(20),
b_code varchar(20),
a_code varchar(20),
--CONSTRAINTS
CONSTRAINT pk_account PRIMARY KEY(account_no),
CONSTRAINT fk_account_1 FOREIGN KEY(b_code) REFERENCES branch(b_code),
CONSTRAINT fk_account_2 FOREIGN KEY(branch_number) REFERENCES branch(branch_number),
CONSTRAINT fk_account_3 FOREIGN KEY(a_code) REFERENCES account_type(a_code)
)
How do I make the relation between these two tables? How to implement the foreign key for the account table with branch when I have one column referencing to two other columns?
Your fk_account_1 will fail when you try to compile it because b_code is not a primary or unique key on table branch. Same problem with fk_account_2, because branch_number is not primary or unique on branch.
The primary key on branch is (branch_number,b_code) so your foreign key should be
CONSTRAINT FK_ACCOUNT_1
FOREIGN KEY (BRANCH, B_CODE)
REFERENCES BRANCH (BRANCH, B_CODE);

Defining foreign key for a composite primary key in SQL Server

I have two tables: Ticket and TicketRelation. I am trying to relate 2 Tickets using the TicketRelation table.
I want to add a cascade constraint to both foreign keys.
I am using SQL Server Management Studio to add the constraints but I get this error:
Introducing FOREIGN KEY constraint 'FK_destiny_ticket' on table 'ticketRelation' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
I also tried to do this with a trigger, but I am not sure how to define it.
Here I provide the tables definitions:
This is the base entity TICKET
CREATE TABLE ticket
(
ticket_id BIGINT,
some_data VARCHAR (50),
CONSTRAINT PK_ticket PRIMARY KEY (ticket_id)
);
and the relational table TICKETRELATION
CREATE TABLE ticketRelation
(
origin_ticket BIGINT,
destiny_ticket BIGINT,
relation_data VARCHAR (50),
CONSTRAINT PK_ticket_relation PRIMARY KEY (origin_ticket, destiny_ticket),
CONSTRAINT FK_origin_ticket FOREIGN KEY (origin_ticket)
REFERENCES ticket(ticket_id),
CONSTRAINT FK_destiny_ticket FOREIGN KEY (destiny_ticket)
REFERENCES ticket(ticket_id),
)
I want to add an ON DELETE CASCADE constraint to both foreign keys:
CONSTRAINT FK_origin_ticket FOREIGN KEY (origin_ticket)
REFERENCES ticket(ticket_id)
ON DELETE CASCADE, -- I want to add this --
CONSTRAINT FK_destiny_ticket FOREIGN KEY (origin_ticket)
REFERENCES ticket(ticket_id)
ON DELETE CASCADE, -- and this --

cycles or multiple cascade paths. SQL Error?

I'm trying to create Employee database for practice. I'm getting this error:
Introducing FOREIGN KEY constraint 'fk_dno' on table 'Employee' may
cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or
ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints ?
What is causing this error?
create table Department(
Dno int not null,
Name_d varchar(30),
primary key(Dno)
)
create table Employee(
E_id int not null,
F_name varchar(30),
L_name varchar(30),
B_date date,
address_e varchar(30),
salary int,
Sex varchar(8),
Cnic varchar(15),
Email varchar(50),
start_date_e date,
primary key (E_id)
)
alter table Department add Mgr_id int
alter table Department add constraint fk_mgr Foreign key(Mgr_id) references Employee(E_id) on update cascade on delete set null
alter table Employee add Dno int
alter table Employee add constraint fk_dno Foreign key(Dno) references Department(Dno) on update cascade on delete set null
Having mutual foreign keys with ON UPDATE CASCADE creates a cycle because, if you modify a row from one, it searches for rows to delete / modify on the other table, which triggers modification in the other table (the one that originated the change) and so on.
Change the ON UPDATE and ON DELETE options for your FK. Evaluate if you need them mutually referencing fields (you might be designing with the wrong attributes)

Foreign Key Cascade On Delete

Assume that i have the following tables
User,Article,Comment
A User can Comment on an Article or write an Article.
I wanted the behavior that:
When i delete a User it should delete all of his Articles and
Comments
When i delete an Article it should delete all of its Comments
So i thought i should use FOREIGN KEYS and tried to model the above as the following
CREATE TABLE [User](
UserId int PRIMARY KEY IDENTITY(1,1),
Username nvarchar(50) NOT NULL
)
CREATE TABLE [Article](
ArticleId int PRIMARY KEY IDENTITY(1,1),
UserId int NOT NULL,
FOREIGN KEY(UserId) references [User](UserId) ON DELETE CASCADE
)
CREATE TABLE [Comment](
CommentId int PRIMARY KEY IDENTITY(1,1),
UserId int Not NULL,
ArticleId int NOT NULL ,
FOREIGN KEY(UserId) references [User](UserId) ON DELETE CASCADE,
FOREIGN KEY(ArticleId) references [Article](ArticleId) ON DELETE CASCADE
)
But the problem comes with the Comment causing
Introducing FOREIGN KEY constraint 'FK__Comment__Article__32E0915F' on table 'Comment' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
My question is how would you model this behavior and still use CASCADE ON DELETE AND FOREIGEN KEYS?
You should just be able to remove the Cascade Delete on the User Foreign Key on the Comment.
As when the user is deleted, this will cascade delete the Article, which will in turn Cascade Delete the comments:
CREATE TABLE [Comment](
CommentId int PRIMARY KEY IDENTITY(1,1),
UserId int Not NULL,
ArticleId int NOT NULL ,
FOREIGN KEY(UserId) references [User](UserId),
FOREIGN KEY(ArticleId) references [Article](ArticleId) ON DELETE CASCADE
)

Composite Foreign Key from multiple related tables

Just beginning to learn about SQL and had a question I couldn't figure out.
I have a setup based on the following tables and their primary keys, the columns with the same name between tables are constrained by foreign keys:
Company:
CompanyId
Division:
CompanyId
DivisionId
Resource:
CompanyId
ResourceId
DivisionResource :
CompanyId
DivisionId
ResourceId
DivisionResource is used to create a many to many relation between division and resource and constrain them so that divisions can only be linked to resources of the same company.
Without the DivisionResource, Division and Resource wouldn't need the CompanyId as a primary key to contain unique records.
So my question is this: Is there a way to create a similar constraint as DivisionResource creates without forcing Division and Resource to have an extra column in its primary key?
ResourceCompany and DivisionCompany in the schema below are connecting tables. They will have CompanyId in their primary key but Resource and Division will have primary keys with one column. This is what you looked for.
Resource -> ResourceCompany
DivisionResource -> ResourceCompany
Division -> DivisionCompany
DivisionResource -> DivisionCompany
create table Company (CompanyId int primary key);
create table DivisionCompany (
CompanyId int foreign key references Company(CompanyId),
DivisionId int,
constraint pk_div_company primary key (DivisionId, CompanyId)
);
create table Division (
DivisionId int primary key,
CompanyId int,
constraint fk_div_company foreign key (DivisionId, CompanyId) references DivisionCompany(DivisionId, CompanyId));
create table ResourceCompany (
CompanyId int foreign key references Company(CompanyId),
ResourceId int,
constraint pk_res primary key (ResourceId, CompanyId));
create table Resource(
ResourceId int primary key,
CompanyId int,
constraint fk_res_company foreign key (ResourceId, CompanyId) references ResourceCompany(ResourceId, CompanyId)
);
create table DivisionResource(
CompanyId int,
DivisionId int,
ResourceId int,
constraint pk_DivRes primary key (DivisionId, ResourceId),
constraint fk_DivCompany foreign key (DivisionId, CompanyId) references DivisionCompany(DivisionId, CompanyId),
constraint fk_ResCompany foreign key (ResourceId, CompanyId) references ResourceCompany(ResourceId, CompanyId)
);
Create INSTEAD OF trigger on insert and update of DivisionResource
The trigger will check if Divistion and Resource have the same company. If they don't, it will fail the modification
Alternatively, it would be even better to have a stored procedure modifying DivisionResource. Then the trigger needs to call it.
I'm assuming that you're trying to create the following schema:
CREATE TABLE company (
companyId int PRIMARY KEY)
CREATE TABLE division (
divisionId int PRIMARY KEY,
companyId int
REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)
CREATE TABLE resource (
resourceId int PRIMARY KEY,
companyId int
REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)
CREATE TABLE divisionResource (
divisionId int
REFERENCES division (divisionId) ON DELETE CASCADE ON UPDATE CASCADE,
resourceId int
REFERENCES resource (resourceId) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (divisionId, resourceId))
Which throws:
Introducing FOREIGN KEY constraint on table 'divisionResource' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Changing either divisionId or resourceId to ON DELETE NO ACTION ON UPDATE NO ACTION will essentially break the referential integrity. What I suggested in my comment was to make a surrogate key. However, it would be better if you created a separate table for resource. This will maintain the referential integrity and also normalize the schema:
CREATE TABLE company (
companyId int PRIMARY KEY)
CREATE TABLE division (
divisionId int PRIMARY KEY,
companyId int
REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)
CREATE TABLE resource (
resourceId int PRIMARY KEY)
CREATE TABLE companyResource (
resourceId int
REFERENCES resource (resourceId) ON DELETE CASCADE ON UPDATE CASCADE,
companyId int
REFERENCES company (companyId) ON DELETE CASCADE ON UPDATE CASCADE)
CREATE TABLE divisionResource (
divisionId int
REFERENCES division (divisionId) ON DELETE CASCADE ON UPDATE CASCADE,
resourceId int
REFERENCES resource (resourceId) ON DELETE CASCADE ON UPDATE CASCADE,
PRIMARY KEY (divisionId, resourceId))