cycles or multiple cascade paths. SQL Error? - sql

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)

Related

How to create tables in SQL when they reference each other in SQL server. Furthermore how to ensure no errors pop up during data insertion

I have two tables Employee and Customer Account. The employee advises the customer account:
Here is the SQL I have written for the Employee Table. (Don't mind the Person(PersonID), it works, since the Person has no foreign keys. But the Customer(SSN) reference suffers from this issue as well.):
CREATE TABLE Employee(
SSN Varchar(50) NOT NULL PRIMARY KEY,
Manages Varchar(50),
PersonID varchar(50) FOREIGN KEY REFERENCES Person(PersonID ),
Advises varchar(50) FOREIGN KEY REFERENCES CustomerAccount(AccountNo),
);
And here is the SQL for the Customer Account Table:
CREATE TABLE CustomerAccount(
AccountNo Varchar(50) NOT NULL PRIMARY KEY,
AdvisiorID VARCHAR(50) FOREIGN KEY REFERENCES Employee(SSN),
OwnerSSN Varchar(50) FOREIGN KEY REFERENCES Customer(SSN),
);
As we can see I can't create either CustomerAccount or Employee since both of them depend on each other. How should I resolve this issue?
Also when inserting using insert statements, it would probably give errors entering data, How should I resolve that?

Mutating table trigger error upon deleting from a table

I have these table definitions
CREATE TABLE EMPLOYEE(
EmployeeID NUMBER(4),
Name VARCHAR2(20),
Hiredate DATE NOT NULL,
Gender VARCHAR(1),
DateOfBirth DATE NOT NULL,
Salary NUMBER(8,2),
Commission NUMBER(8, 2),
DName VARCHAR(20),
PName VARCHAR(20),
Phone NUMBER(8) NOT NULL,
GLetter VARCHAR(1),
CONSTRAINT EMPLOYEE_EMPLOYEEID_PK PRIMARY KEY(EMPLOYEEID),
CONSTRAINT EMPLOYEE_DNAME_FK FOREIGN KEY(DName) REFERENCES DEPARTMENT(DName) ON DELETE CASCADE,
CONSTRAINT EMPLOYEE_PNAME_FK FOREIGN KEY(PName) REFERENCES POSITION(PName) ON DELETE CASCADE,
CONSTRAINT EMPLOYEE_GLETTER_FK FOREIGN KEY(GLetter) REFERENCES GRADE(GLetter) ON DELETE CASCADE,
CONSTRAINT GENDER_CK CHECK (Gender='M' or Gender='F')
);
CREATE TABLE LOGIN(
Username VARCHAR(20),
Password VARCHAR(20),
EmployeeID NUMBER(4),
CONSTRAINT LOGIN_USERNAME_PK PRIMARY KEY(Username),
CONSTRAINT LOGIN_EMPLOYEEID_FK FOREIGN KEY(EmployeeID) REFERENCES EMPLOYEE(EmployeeID) ON DELETE CASCADE
);
CREATE SEQUENCE TRANSACTION_SEQ START WITH 6;
CREATE TABLE TRANSACTION(
TransactionID NUMBER(4) DEFAULT TRANSACTION_SEQ.NEXTVAL,
TransactionDate DATE,
Username VARCHAR(20),
EmployeeID NUMBER(4),
CONSTRAINT TRANSACTION_TRANSACTIONID_PK PRIMARY KEY(TransactionID),
CONSTRAINT TRANSACTION_USERNAME_FK FOREIGN KEY(Username) REFERENCES LOGIN(Username) ON DELETE CASCADE,
CONSTRAINT TRANSACTION_EMPLOYEEID_FK FOREIGN KEY(EmployeeID) REFERENCES EMPLOYEE(EmployeeID) ON DELETE CASCADE
);
and this trigger
CREATE OR REPLACE TRIGGER EMPLOYEE_TRANSACTION
BEFORE INSERT OR UPDATE OR DELETE ON EMPLOYEE
FOR EACH ROW
DECLARE
ID NUMBER(4);
USR VARCHAR(20);
BEGIN
SELECT LOWER(USER)
INTO USR
FROM DUAL;
SELECT EMPLOYEEID
INTO ID
FROM LOGIN
WHERE USERNAME = USR;
INSERT INTO TRANSACTION VALUES(DEFAULT, SYSDATE, USR, ID);
END;
/
my problem arises when trying to delete an employee.
basically, the trigger finds out the employeeid of the user who is making the changes and inserts it and other values to the transaction table. i get this error:
Error report -
ORA-04091: table ---.LOGIN is mutating, trigger/function may not see it
ORA-06512: at "---.EMPLOYEE_TRANSACTION", line 9
ORA-04088: error during execution of trigger '---.EMPLOYEE_TRANSACTION'
is oracle taking into account the possibility that i am deleteing an employee whose id (which is going to be deleted from table LOGIN) is that of the oracle USER?
any solutions? thank you very much!
If we assume that this fiddle is a reproducible test case that demonstrates your problem (note that I had to make several changes to your code in order to be able to do things like inserting the test data), the issue is that the foreign key constraint on the login table is defined to do a cascade delete (on delete cascade). That means that when you are deleting a row from employee, login will be mutating (Oracle is in the middle of deleting the child row). Thus you can't query it from within a trigger on employee.
Depending on exactly what you are hoping to accomplish, you have a few options
Don't query the login table and don't store the employeeID in the transaction table. If you have the username that performed the operation in the transaction table, you can always look up their employeeID.
Don't use triggers to populate the transaction table. If you have a stored procedure that deletes an employee, it makes more sense for that procedure to do the work of logging the transaction.
Don't define your constraints as on delete cascade. That would mean, though, that you'd need to delete the login row prior to deleting the employee row. Here is an example where we remove the on delete cascade from the LOGIN_EMPLOYEEID_FK constraint and add a statement to delete the associated login row.

Referencing the primary key twice as foreign key in MS Access using SQL is causing an error

I get an error when I try to reference the primary key as a foreign key in other queries:
There is already a relationship named " DepartmentNameFK" in the current database.
CREATE TABLE PROJECT
(
ProjectID varchar(50),
Name varchar(50),
MaxHours FLOAT,
StartDate Date,
EndDate Date,
DepartmentName varchar(50),
CONSTRAINT ProjectIDPK PRIMARY KEY (ProjectID),
CONSTRAINT DepartmentNameFK FOREIGN KEY (DepartmentName) **[ so here I am referencing for the second time, THIS IS NOT PART OF CODE, JUST EXPLANATION]**
REFERENCES DEPARTMENT ON DELETE NO ACTION ON UPDATE CASCADE
);
The error seems very clear - you already have a foreign key constraint by the name of DepartmentNameFK - but all database objects (and constraints are database objects) must have a unique, separate name so you can refer to them.
So here - just call your FK constraint something else:
CREATE TABLE PROJECT
(
ProjectID varchar(50),
Name varchar(50),
MaxHours FLOAT,
StartDate Date,
EndDate Date,
DepartmentName varchar(50),
CONSTRAINT ProjectIDPK PRIMARY KEY (ProjectID),
-- just call the constraint **SOMETHING ELSE** other than "DepartmentNameFK"
CONSTRAINT DepartmentNameFK2
FOREIGN KEY (DepartmentName)
REFERENCES DEPARTMENT ON DELETE NO ACTION ON UPDATE CASCADE
);
My suggestion would be to name your FK constraints
FK_(parent table)_(referenced table)
so in your case:
FK_Project_Department
If your other FK is in another table, it would be
FK_OtherTable_Department
and thus you would not have any clashes of already existing names.....

Missing Keyword in SQL Code on Foreign Keys unable to create the table

Trying to create a table with an SQL code, but I'm getting an error:
Missing keyword
in regards to the foreign key.
CREATE TABLE Staff
(
staffID VARCHAR(5) NOT NULL,
name VARCHAR(50),
position VARCHAR(30),
branchID VARCHAR(5),
PRIMARY KEY (staffID),
FOREIGN KEY (branchID) REFERENCES Branch ON UPDATE CASCADE
);
Unlike other RDBMS (such as MySQL for example), Oracle does not support the ON UPDATE clause in foreign keys. You would just need to remove that part of the declaration.
Try:
CREATE TABLE Staff (
staffID VARCHAR(5) NOT NULL,
name VARCHAR(50),
position VARCHAR(30),
branchID VARCHAR(5),
PRIMARY KEY (staffID),
FOREIGN KEY (branchID) REFERENCES Branch(branchID) --ON UPDATE CASCADE
);
Demo on DB Fiddle
The logic behind this Oracle behavior is that the referred column is not supposed to change, since it must be PRIMARY KEY (or a UNIQUE column). I believe that this limitation makes sense... they just don't want to give users enough rope to hang themselves with.

On Delete Cascade SQL

The code is written as a script and when i run this script second time, is doesn't drop table EMPLOYEE_TBL because of which various errors are occuring.
Now the question is: Why doesn't DROP TABLE EMPLOYEE_TBL WORK?
DROP TABLE EMPLOYEE_TBL;
DROP TABLE EMPLOYEE_PAY_TBL;
Create table EMPLOYEE_TBL(
EMP_ID VARCHAR(9),
LAST_NAME VARCHAR(15) NOT NULL,
FIRST_NAME VARCHAR(15) NOT NULL,
MIDDLE_NAME VARCHAR(15),
ADDRESS VARCHAR(50) NOT NULL,
CITY VARCHAR(15) NOT NULL,
STATE VARCHAR(10) NOT NULL,
ZIP NUMBER(5) NOT NULL,
PHONE VARCHAR(15),
PAGER VARCHAR(15) );
Alter table EMPLOYEE_TBL
add constraints pk_EMPLOYEE_TBL primary key (EMP_ID);
commit;
Create table EMPLOYEE_PAY_TBL (
EMP_ID VARCHAR(9),
POSITION VARCHAR(15) NOT NULL,
DATE_HIRE DATE,
PAY_RATE DECIMAL(4,2) NOT NULL,
DATE_LAST_RAISE DATE,
Salary Decimal (4, 2),
Bonus Decimal (4, 2) );
--CONSTRAINT EMP_FK FOREIGN KEY (EMP_ID_ REFERENCES
--EMPLOYEE_TBL (EMP_ID));
commit;
Alter table EMPLOYEE_PAY_TBL
add constraints pk_EMPLOYEE_PAY_TBL primary key (EMP_ID);
alter table EMPLOYEE_PAY_TBL
add constraints fk_EMP_ID foreign key (EMP_ID) references EMPLOYEE_TBL (EMP_ID) ON DELETE CASCADE;
The second time, when you try to drop EMPLOYEE_TBL you have this constraint:
alter table EMPLOYEE_PAY_TBL
add constraints fk_EMP_ID foreign key (EMP_ID) references EMPLOYEE_TBL (EMP_ID)
ON DELETE CASCADE;
So you must before remove this constraint and then remove the table.
For further info, please post your error
You can't drop TABLE EMPLOYEE_TBL because it's referenced by EMPLOYEE_PAY_TBL.
The ON DELETE CASCADE option refers to deleting rows in the parent table, not to dropping the parent table.
Judging by the DDL you are most probably using Oracle. In that case you can use the cascade keyword when dropping the table:
DROP TABLE EMPLOYEE_TBL CASCADE CONSTRAINTS;
DROP TABLE EMPLOYEE_PAY_TBL CASCADE CONSTRAINTS;
The CASCADE option for DROP TABLE will automatically alsso drop all foreign keys referencing the table being droppen.