Mutating table trigger error upon deleting from a table - sql

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.

Related

why liquibase run automatically the rollback sql statement

I'm learning liquibase, I'm trying to write an sql changset that allows the possibility to rollback later on.
Here is my syntax:
--changeset me:1
create table DEPARTMENT (id SERIAL not null, name varchar(50) not null, person_id int, primary key (id), constraint person_foreign_key foreign key (person_id) references PERSON(id));
--rollback
drop table DEPARTMENT;
When running liquibase:update, the table department is created, but it is deleted by the second query.
what is the correct syntax to have the rollback statement without the removal of the department table?
I'm using liquibise version 4.7.1
It seems that the drop statement should be on the same line as --rollback.
Here is the changeset file:
-- liquibase formatted sql
-- changeset me:1
create table DEPARTMENT (
id SERIAL not null,
name varchar(50) not null,
person_id int,
primary key (id),
constraint person_foreign_key foreign key (person_id) references PERSON(id)
);
--rollback drop table DEPARTMENT;

I'm repeatedly getting this "integrity constraint violated- parent key not found" error

The problem goes like: I have 2 tables Employee and Department. Both tables have department_id and manager_id in them. I have a primary key employee_id in table employee and primary key department_id in the table department. I have to make department_id and manager_id of table employee foreign keys to department_table. Now, I've spent 15+ hours (i know hard to believe) on trying to do so but failed. After making the foreign keys, I'm able to insert values into department table and then when I try to enter values into employee table I get the "invalid constraint violated" error. I know this might be a very basic thing but I'm really new to this and this foreign key stuff still confuses me. Can someone tell me what is wrong with my code, why am I only able to insert values into department table and not into employee table.
Here are the contents of my spool file:
CREATE TABLE EMPLOYEE(EMPLOYEE_ID NUMBER(6) CONSTRAINT EMP_NNPK PRIMARY KEY NOT NULL, FIRST_NAME VARCHAR2(20) CONSTRAINT FIRSTNAME_NN NOT NULL, LAST_NAME VARCHAR2(20) CONSTRAINT LASTNAME_NN NOT NULL, EMAIL VARCHAR2(25) CONSTRAINT EMAIL_UKNN UNIQUE NOT NULL, PHONE_NUMBER VARCHAR2(20) DEFAULT '0000000000', HIRE_DATE DATE CONSTRAINT HIREDATE_NN NOT NULL, JOB_ID VARCHAR2(10) CONSTRAINT JOBID_NN NOT NULL, SALARY NUMBER(8,2) CONSTRAINT SALARY_CHECK CHECK(SALARY >5000), COMMISSION_PCT NUMBER(2,2), MANAGER_ID NUMBER(6), DEPARTMENT_ID NUMBER(4) CONSTRAINT DEPTID_NN NOT NULL);
Table created.
SQL> CREATE TABLE DEPARTMENT(DEPARTMENT_ID NUMBER(4) CONSTRAINT DEPT_NN_PK PRIMARY KEY NOT NULL, DEPARTMENT_NAME VARCHAR2(30) CONSTRAINT DEPTNAME_NN NOT NULL, MANAGER_ID NUMBER(6) CONSTRAINT MANAGERID_UK UNIQUE, LOCATION_ID NUMBER(4));
Table created.
SQL> ALTER TABLE EMPLOYEE ADD CONSTRAINT DEP_FK FOREIGN KEY(DEPARTMENT_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID);
Table altered.
SQL> ALTER TABLE EMPLOYEE ADD CONSTRAINT MAN_FK FOREIGN KEY(MANAGER_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID);
Table altered.
SQL> INSERT INTO DEPARTMENT VALUES('&DEPARTMENT_ID','&DEPARTMENT_NAME','&MANAGER_ID','&LOCATION_ID');
Enter value for department_id: 10
Enter value for department_name: ADMINISTRATION
Enter value for manager_id: 200
Enter value for location_id: 1700
old 1: INSERT INTO DEPARTMENT VALUES('&DEPARTMENT_ID','&DEPARTMENT_NAME','&MANAGER_ID','&LOCATION_ID')
new 1: INSERT INTO DEPARTMENT VALUES('10','ADMINISTRATION','200','1700')
1 row created.
SQL> INSERT INTO EMPLOYEE VALUES('&EMPLOYEE_ID','&FIRST_NAME','&LAST_NAME','&EMAIL','&PHONE_NUMBER','&HIRE_DATE','&JOB_ID','&SALARY','&COMMISSION_PCT','&MANAGER_ID','&DEPARTMENT_ID');
Enter value for employee_id: 174369
Enter value for first_name: OLIVIA
Enter value for last_name: MATOS
Enter value for email: OLIVIA#GMAIL.COM
Enter value for phone_number: 8989166387
Enter value for hire_date: 03-SEP-2021
Enter value for job_id: 20ABC101
Enter value for salary: 100000.00
Enter value for commission_pct: 0.10
Enter value for manager_id: 200
Enter value for department_id: 10
old 1: INSERT INTO EMPLOYEE VALUES('&EMPLOYEE_ID','&FIRST_NAME','&LAST_NAME','&EMAIL','&PHONE_NUMBER','&HIRE_DATE','&JOB_ID','&SALARY','&COMMISSION_PCT','&MANAGER_ID','&DEPARTMENT_ID')
new 1: INSERT INTO EMPLOYEE VALUES('174369','OLIVIA','MATOS','OLIVIA#GMAIL.COM','8989166387','03-SEP-2021','20ABC101','100000.00','0.10','200','10')
INSERT INTO EMPLOYEE VALUES('174369','OLIVIA','MATOS','OLIVIA#GMAIL.COM','8989166387','03-SEP-2021','20ABC101','100000.00','0.10','200','10')
*
ERROR at line 1:
ORA-02291: integrity constraint (SYSTEM.DEP_FK) violated - parent key not found
Your foreign key is referencing the wrong table FOREIGN KEY(DEPARTMENT_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID);
should be
FOREIGN KEY(DEPARTMENT_ID) REFERENCES DEPARTMENT (DEPARTMENT_ID);
It is trying to validate department ID against the ID in the employee table.
When you add a foreign key constraint all you doing is telling the database to ensure any value being inserted into a column exists in the related table (the other side of the foreign key).
so ALTER TABLE ABC ADD CONSTRAINT TEST_FK FOREIGN KEY(MY_FK_COL) REFERENCES XYZ(MY_PK_COL); is telling the database that each time someone tries to insert or update the MY_FK_COL column in the ABC table that the database should check that the value already exists in the MY_PK_COL column of the XYZ table. If the value does not exist you get your ORA-02291: integrity constraint (TEST_FK) violated - parent key not found error telling you the value does not already exist in the parent / related table / the other side of the foreign key
The main reason for this is to ensure valid data. Take your employee -> department example, you create a foreign key to ensure that employees can only be added to departments that actually exist.
Also you really want to use the right data-types as you have defined your IDs as number but are then inserting them as text. It probably won't make a difference but it does mean that there needs to be some conversion going on in the database and it can cause some oddities. Just remove the single quotes around your numeric fields.
Try to COMMIT after inserting the manager, before inserting the employee reporting to him .

Delete/Modify row in one table based on a condition - Oracle DBMS

I have a table structure like
create table EMPLOYE (
CodeEmploye varchar2(100) not null,
NAS varchar2(100),
CONSTRAINT employe_pk primary key (CodeEmploye)
);
create table SALAIRE (
CodeEmploye varchar2(100) not null,
Mois number not null,
CONSTRAINT salaire_pk primary key (CodeEmploye, Mois),
CONSTRAINT salaire_code_employe_fk FOREIGN KEY(CodeEmploye) REFERENCES EMPLOYE(CodeEmploye)
);
I want to add a constraint where I should not be allowed to modify/delete a row in EMPLOYE table if the same employee exist in SALAIRE table.
What is the best way to do that ?
As you have define the foreign key relationship between two tables by "CodeEmployee" column, what you want has been achieved.
A little bit extension is that if you add "ON DELETE CASCADE" following the fk declaration, once you delete any row form employee table, all the related records in the salary table will be deleted as well.
One of the best ways to do is by creating a foreign key constraint on the "CodeEmploye" column during CREATE TABLE or ALTER TABLE statements. In your case, it is already created (salaire_code_employe_fk) as part of your CREATE statement.
A foreign key constraint ensures that an employee row from the parent table (EMPLOYE) cannot be modified/deleted if the same employee exists in the child table (SALAIRE).
In this case, when you create the order_items table, you define a foreign key constraint with the DELETE CASCADE option as follows:
CREATE TABLE order_items
(
order_id NUMBER( 12, 0 ),
-- other columns
-- ...
CONSTRAINT fk_order_items_orders
FOREIGN KEY( order_id )
REFERENCES orders( order_id )
ON DELETE CASCADE
);
By doing this, whenever you delete a row from the orders table, for example:
DELETE
FROM
orders
WHERE
order_id = 1;
All the rows whose order id is 1 in the order_items table are also deleted automatically by the database system.

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)

Error while inserting data in table with Composite primary key

I have table
create table INVOICE
(
brok_dlr_code VARCHAR2(20),
invoice_date DATE,
ba_trxn_date_from DATE,
ba_trxn_date_to DATE,
mf_invoice_no VARCHAR2(40)
);
I created composite primary key
ALTER TABLE BROKER_INVOICE_HISTORY
ADD CONSTRAINT PK_BROKER_INVOICE_HISTORY
PRIMARY KEY(brok_dlr_code, ba_trxn_date_from, ba_trxn_date_to);
there is no record with same brok_dlr_code but executing the script with same ba_trxn_date and ba_trxn_date_to dates but raises error as
ORA-20005: ORA-00001: unique constraint violated
Since there were few records already got inserted, then again running the script cause the script to begin inserting same data. This caused unique constraint violation. Hence old data had to be truncate and re-run the script will not cause this unique constraint.