Oracle Trigger on two tables - oracle

I am trying to create a BEFORE UPDATE trigger on the two tables purchaseorderdetail and purchaseorderheader as shown below. I would like to implement this trigger on PurchaseOrderHeader table that prohibits updates of the PurchaseOrderHeader.SubTotal column if the corresponding data in the PurchaseOrderDetail table is not consistent with the new value of the PurchaseOrderHeader.SubTotal column.
CREATE TABLE purchaseorderheader(
purchaseorderid NUMBER(4),
revisionnumber NUMBER(2),
status NUMBER(1),
employeeid NUMBER(3),
vendorid NUMBER(4),
shipmethodid NUMBER(1),
orderdate TIMESTAMP,
shipdate TIMESTAMP,
subtotal FLOAT(10),
taxamt FLOAT(10),
freight FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderid)
);
CREATE TABLE purchaseorderdetail(
purchaseorderid NUMBER(4),
purchaseorderdetailid NUMBER(4),
duedate TIMESTAMP,
orderqty NUMBER(6),
productid NUMBER(6),
unitprice FLOAT(10),
receivedqty FLOAT(10),
rejectedqty FLOAT(10),
modifieddate TIMESTAMP,
PRIMARY KEY(purchaseorderdetailid),
CONSTRAINT fk_orderid FOREIGN KEY (purchaseorderid) REFERENCES purchaseorderheader(purchaseorderid)
);
What I have come up with so far, any help?
CREATE OR REPLACE TRIGGER Header_Before_Subtotal BEFORE UPDATE
ON purchaseorderheader
FOR EACH ROW
BEGIN
IF(:NEW.subtotal <> (SELECT unitprice*orderqty FROM purchaseorderdetail GROUP BY purchaseorderid)) THEN
RAISE_APPLICATION_ERROR(-20001, 'Subtotal is not equal to unitprice * order quantity, check again.');
END IF;
END;

Compute total separately (and reference the master key), and then compare that value to new subtotal.
CREATE OR REPLACE TRIGGER Header_Before_Subtotal
BEFORE UPDATE
ON purchaseorderheader
FOR EACH ROW
DECLARE
l_total number;
BEGIN
SELECT d.unitprice * d.orderqty
INTO l_total
FROM purchaseorderdetail d
WHERE d.purchaseorderid = :new.purchaseorderid;
IF :NEW.subtotal <> l_total THEN
RAISE_APPLICATION_ERROR(-20001, 'Subtotal is not equal to unitprice * order quantity, check again.');
END IF;
END;
/

Related

SQL: ORA-02291: integrity constraint violated - parent key not found

I am creating this code SQL code and I keep getting the same error from every line of the insert statements after the errors begin here statement. the error is, ORA-02291: integrity constraint violated - parent key not found. I think it has something to do with the employee section constraint EMPSUPERVRFK but, that is the only constraint that the error message would lead to.
-- keep these two commands at the top of every sql file
set echo on
set linesize 120
delete from Employee;
commit;
-- insert only managers first with their dno is null
INSERT INTO Employee VALUES
('James','E','Borg',888665555,'10-NOV-1937','450 Stone, Houston, TX','M',55000,null,null);
INSERT INTO Employee VALUES
('Franklin','T','Wong',333445555, to_date('1955-12-08', 'YYYY-MM-DD'), '638 Voss, Houston, TX','M',40000,888665555,null);
INSERT INTO Employee VALUES
('Jennifer','J','Zelaya',987654321,'20-JUN-1941','291 Berry, Bellaire, TX','F',43000,888665555,null);
delete from Department;
commit;
insert into Department values ('Research',5,333445555,'22-MAY-1988');
insert into Department values ('Headquarters',1,888665555,'19-JUN-1981');
insert into Department values ('Administration',1,888665555,'01-JAN-1995');
-- now, update employee.dno for managers
UPDATE Employee SET dno = 1 WHERE ssn = 888665555;
UPDATE Employee SET dno = 5 WHERE ssn = 333445555;
-- need to update the rest of managers
-- insert the rest of non-manager employees, supervisors first
--errors begin here
delete from Employee;
commit;
INSERT INTO Employee VALUES ('John','B','Smith',123456789,'09-JAN-1965','731 Fondren, Houston, TX','M',30000,333445555,5);
insert into Employee values ('Alica','J','Zelya',999887777,'19-JAN-1968','3321 Castle, Spring, TX','F',25000,987654321,4);
insert into Employee values ('Ramesh','K','Narayan',666884444,'15-SEP-1962', '975 Fire Oak, Humnle, TX','M',38000,333445555,5);
insert into Employee values ('Joyce','A','English',453453453,'31-JUL-1972','5631 Rice, Houston, TX','F',25000,333445555,5);
insert into Employee values ('Ahmad','V','Jabbar',987987987,'29-MAR-1969','980 Dallas, Houston, TC','M',25000,987654321,4);
--Project
delete from PROJECT;
commit;
insert into PROJECT values ('ProductY',2,'Sugarland',5);
insert into PROJECT values ('ProductZ',3,'Houston',5);
insert into PROJECT values ('Computerication',10,'Stafford',4);
insert into PROJECT values ('Reorganization',20,'Houston',1);
insert into PROJECT values ('Newbenefits',30,'Stafford',4);
--dept_Locations
delete from DEPT_LOCATIONS;
commit;
insert into DEPT_LOCATIONS values (1, 'Houston');
insert into DEPT_LOCATIONS values (4,'Stafford');
insert into DEPT_LOCATIONS values (5,'Bellaire');
insert into DEPT_LOCATIONS values (5,'Sugarland');
insert into DEPT_LOCATIONS values (5,'Houston');
--works_on 16
delete from WORKS_ON;
commit;
insert into WORKS_ON values (123456789,1,32.5);
insert into WORKS_ON values (123456789,2,7.5);
insert into WORKS_ON values (666884444,3,40.0);
insert into WORKS_ON values (453453453,1,20.0);
insert into WORKS_ON values (453453453,2,20.0);
insert into WORKS_ON values (333445555,2,10.0);
insert into WORKS_ON values (333445555,3,10.0);
insert into WORKS_ON values (333445555,10,10.0);
insert into WORKS_ON values (333445555,20,10.0);
insert into WORKS_ON values (999887777,30,30.0);
insert into WORKS_ON values (999887777,10,10.0);
insert into WORKS_ON values (987987987,10,35.0);
insert into WORKS_ON values (987987987,30,5.0);
insert into WORKS_ON values (987654321,30,20.0);
insert into WORKS_ON values (987654321,20,15.0);
insert into WORKS_ON values (888665555,20,null);
--dependent 7
delete from DEPENDENT;
commit;
insert into DEPENDENT values (333445555,'Alice','F','05-APR-1986','Daughter');
insert into DEPENDENT values (333445555,'Theodore','M','25-OCT-1983','Son');
insert into DEPENDENT values (333445555,'Joy','F', '03-MAY-1958','Spouse');
insert into DEPENDENT values (987654321,'Abner','M', '28-FEB-1942','Spouse');
insert into DEPENDENT values (123456789,'Michael','M','04-JAN-1988','Son');
insert into DEPENDENT values (123456789,'Alice','F','30-DEC-1988','Daughter');
insert into DEPENDENT values (123456789,'Elizabeth','F', '05-MAY-1967','Spouse');
-----------------------------------------------------------------------------------
set echo on
set linesize 120
drop table Employee cascade constraints;
commit;
create table Employee
(
fname varchar2(15),
minit varchar2(1), -- can be char
lname varchar2(15),
ssn number,
bdate date,
address varchar2(50),
sex varchar2(1) CHECK(Sex = 'M' or Sex = 'F'),
salary number CHECK(20000 <= salary AND 100000 >= salary),
superssn number,
dno number DEFAULT 0,
constraint EMPPK
primary key(ssn),
constraint EMPSUPERVRFK
foreign key(superssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Department cascade constraints;
commit;
create table Department
(
dname varchar2(15),-- NOT NULL,
dnumber number,
mgrssn number,
mgrstartdate date,
constraint DEPTPK
primary key(dnumber),
constraint DEPTMGRFK
foreign key(mgrssn) references Employee(ssn)
ON DELETE SET NULL
);
alter table Employee add
constraint EMPDEPTFK foreign key(dno) references Department(dnumber)
ON DELETE SET NULL;
drop table DEPT_LOCATIONS;
create table DEPT_LOCATIONS
(
Dnumber number,
Dlocation varchar2(15),
constraint PK_DnoDloc primary key(Dnumber,Dlocation)
);
COMMIT;
drop table PROJECT;
create table PROJECT
(
Pname varchar2(15),
Ponumber number primary key,
Plocation varchar2 (15),
Dnum number,
foreign key (Dnum) references Department(dnumber)
);
Commit;
drop table DEPENDENT;
create table DEPENDENT
(
Essn number,
Dependent_name varchar2(15),
Sex Char,
Bdate Date,
Relationship varchar2(15),
foreign key(Essn) references Employee(ssn) --
ON DELETE SET NULL,
constraint PK_essn
primary key(Essn,Dependent_name)
);
COMMIT;
drop table WORKS_ON;
create table WORKS_ON
(
Essn number,
Pno number,
Hours number,
foreign key(Essn) references Employee(ssn)--
ON DELETE SET NULL,
foreign key(Pno) references PROJECT(Ponumber)
ON DELETE SET NULL,
constraint PK_SSN
primary key(Essn, Pno)
);
commit;
----------------------------------------------------------------
-- keep these two commands at the top of every sql file
set echo on
set linesize 120
-- test queries, not to be submitted
select count(*) from employee;
select count(*) as DEPT_COUNT from department;
-- comment out the above queries for your homework
-- a the first name, last name of employees who work in department 5.
select fname, lname from employee where dno = 5;
-- b the first name, last name of every employee and name of his/her department
select E.fname as FIRST_NAME, E.lname LAST_NAME, D.dname DEPARTMENT_NAME
from employee E, department D
where E.dno = D.dnumber;
--c The first name, last name of employees who works at the 'Research' department
select e.fname , e.lname , Dname
from employee e inner join department d on e.dno=d.dname
where d.name ='Research';
--d. The first name, last name of employee who is the manager of the 'Research' department
select e.fname , e.lname , Dname
from employee e inner join department d on e.dno=d.dname
where d.name ='Research' and e.super_ssn=d.mgr_ssn;
--e. The first name, last name of employees who works on the 'Computerization' project.
select e.fname,e.lname
from employee e inner join department d on e.dno=d.dnumber inner join project p on d.dnumber=p.dnum
where p.pname="Computerization";
this happens because you are inserting values to table that depends on other table that is still empty, you should insert on that table first before this one
for example, suppose you have employee table, and department table, in which every employee must be assigned to a department, so when you input employee Bob to department IT, it would result in error, since there is no IT yet in department table. so you need to input IT on department table, then you can input Bob to employee table
or, you can disable integrity check when importing sql, but this setting is different for each DB engine, so I can't give you an example

How to implement this trigger on Oracle SQL?

I have found an exercise in the SQL book I study, which is not solved and I can not solve it.
The goal is to implement a trigger that avoids overlapping contracts. If a customer with a current contract signs a new one, the end date of the previous one will be one day before the new start date.
Tables given are:
CREATE TABLE CLIENTS (
clientId VARCHAR2(15),
DNI VARCHAR2(9),
name VARCHAR2(100) NOT NULL,
surname VARCHAR2(100) NOT NULL,
sec_surname VARCHAR2(100),
eMail VARCHAR2(100) NOT NULL,
phoneN NUMBER(12),
birthdate DATE,
CONSTRAINT PK_CLIENTS PRIMARY KEY (clientId),
CONSTRAINT UK1_CLIENTS UNIQUE (DNI),
CONSTRAINT UK2_CLIENTS UNIQUE (eMail),
CONSTRAINT UK3_CLIENTS UNIQUE (phoneN),
);
CREATE TABLE contracts(
contractId VARCHAR2(10),
clientId VARCHAR2(15),
startdate DATE NOT NULL,
enddate DATE,
contract_type VARCHAR2(50),
address VARCHAR2(100) NOT NULL,
town VARCHAR2(100) NOT NULL,
ZIPcode VARCHAR2(8) NOT NULL,
country VARCHAR2(100) NOT NULL,
CONSTRAINT PK_contracts PRIMARY KEY (contractId),
CONSTRAINT FK_contracts1 FOREIGN KEY (clientId) REFERENCES CLIENTS
);
Any suggestions?
I agree with the posted comments that it helps to have some specifics about what is failing in the prior attempts, and I would also recommend not using a TRIGGER at all for this kind of thing.
But as this is for a study exercise, here are some examples that might be a starting place.
I've modified your tables to disallow NULL PRIMARY KEYs in these examples.
To get started, create the tables:
CREATE TABLE CLIENTS (
CLIENTID VARCHAR2(15) NOT NULL,
DNI VARCHAR2(9),
NAME VARCHAR2(100) NOT NULL,
SURNAME VARCHAR2(100) NOT NULL,
SEC_SURNAME VARCHAR2(100),
EMAIL VARCHAR2(100) NOT NULL,
PHONEN NUMBER(12),
BIRTHDATE DATE,
CONSTRAINT PK_CLIENTS PRIMARY KEY (CLIENTID),
CONSTRAINT UK1_CLIENTS UNIQUE (DNI),
CONSTRAINT UK2_CLIENTS UNIQUE (EMAIL),
CONSTRAINT UK3_CLIENTS UNIQUE (PHONEN)
);
CREATE TABLE CONTRACTS (
CONTRACTID VARCHAR2(10) NOT NULL,
CLIENTID VARCHAR2(15) NOT NULL,
STARTDATE DATE NOT NULL,
ENDDATE DATE,
CONTRACT_TYPE VARCHAR2(50),
ADDRESS VARCHAR2(100) NOT NULL,
TOWN VARCHAR2(100) NOT NULL,
ZIPCODE VARCHAR2(8) NOT NULL,
COUNTRY VARCHAR2(100) NOT NULL,
CONSTRAINT PK_CONTRACTS PRIMARY KEY (CONTRACTID),
CONSTRAINT FK_CONTRACTS1 FOREIGN KEY (CLIENTID) REFERENCES CLIENTS
);
Then, create the first CLIENTs:
INSERT INTO CLIENTS VALUES (1,NULL,'Frodo','Baggins',NULL,'the.real.frodo#adventure.com',NULL,NULL);
INSERT INTO CLIENTS VALUES (2,NULL,'Chewbacca','UNKNOWN',NULL,'chewio.#kashyyyk.org',NULL,NULL);
COMMIT;
Then create a TRIGGER. In this first example, the TRIGGER is an AFTER STATEMENT type.
It is simple but inefficient since it evaluates every CLIENT after each INSERT statement.
Against a large data set, or in the face of multiple TRIGGERs, this could be a problem.
This TRIGGER will check for the prior contract and will set its ENDDATE to one day before the new contract, if it is null or after the start of the new contract.
CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
AFTER INSERT ON CONTRACTS
BEGIN
MERGE INTO CONTRACTS
USING (
SELECT CONTRACTID,
CANDIDATE_ENDDATE AS ENDDATE
FROM
(SELECT CONTRACTS.CONTRACTID,
(TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
FROM CONTRACTS)
WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
END;
/
Then, test it out.
Add the initial contracts. No enddate changes expected, as these are the first. Frodo's contract here has an end-date already set.
INSERT INTO CONTRACTS VALUES('Break-Ring',1,TO_DATE('19560511','YYYYMMDD'), TO_DATE('19851014','YYYYMMDD'), NULL, 'No 1', 'Doom Mountain', 'MORD', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('SaveGalaxy',2,TO_DATE('19770615','YYYYMMDD'), NULL, NULL, 'No 75', 'Rwookrrorro', 'RWKR', 'Kashyyyk');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 14-OCT-85
SaveGalaxy 2 15-JUN-77
Then add new contracts.
Frodo's new contract starts before the end of his existing contract, so the enddate will be adjusted.
Chewie's initial contract had no ENDDATE, so it will be adjusted as well.
INSERT INTO CONTRACTS VALUES('GoBackHome',1,TO_DATE('19570219','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
INSERT INTO CONTRACTS VALUES('DefendHoth',2,TO_DATE('19801115','YYYYMMDD'), NULL, NULL, 'Meteor Crater', 'Ice Ridge', 'METEO', 'Hoth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80
And as other contracts are signed, the pattern continues:
INSERT INTO CONTRACTS VALUES('GoWedding',2,TO_DATE('19830309','YYYYMMDD'), NULL, NULL, 'Main Hall', 'Grand Palace', 'ALLNC', 'Coruscant');
INSERT INTO CONTRACTS VALUES('Gardening',1,TO_DATE('19570503','YYYYMMDD'), NULL, NULL, 'No 13', 'Hobbiton', 'HBTN', 'Middle-Earth');
SELECT CONTRACTID, CLIENTID, STARTDATE, ENDDATE FROM CONTRACTS ORDER BY CLIENTID ASC, STARTDATE ASC;
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57 02-MAY-57
Gardening 1 03-MAY-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80 08-MAR-83
GoWedding 2 09-MAR-83
To stabilize the workload on this query, a COMPOUND TRIGGER may be used instead. This second example achieves the same result as the first, but only interrogates the CONTRACTs of CLIENTs that have changed:
First, ROLLBACK;
Then, create a type to be used by the TRIGGER:
CREATE OR REPLACE TYPE NUMBER_LIST IS TABLE OF NUMBER;
/
Then create the COMPOUND TRIGGER:
CREATE OR REPLACE TRIGGER CONTRACT_ENDDATE_ADJUSTER
FOR INSERT ON CONTRACTS
COMPOUND TRIGGER
V_CLIENTS NUMBER_LIST;
BEFORE STATEMENT
IS
BEGIN
V_CLIENTS:= NUMBER_LIST();
END BEFORE STATEMENT;
AFTER EACH ROW
IS
BEGIN
V_CLIENTS.EXTEND();
V_CLIENTS(V_CLIENTS.COUNT) := :NEW.CLIENTID;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
MERGE INTO CONTRACTS
USING (
SELECT CONTRACTID,
CANDIDATE_ENDDATE AS ENDDATE
FROM
(SELECT CONTRACTS.CONTRACTID,
(TRUNC(LEAD(STARTDATE) OVER (PARTITION BY CLIENTID ORDER BY STARTDATE ASC) - 1)) AS CANDIDATE_ENDDATE,
DENSE_RANK() OVER (PARTITION BY CLIENTID ORDER BY STARTDATE DESC) AS CONTRACT_ORDER
FROM CONTRACTS
WHERE CONTRACTS.CLIENTID IN (SELECT * FROM TABLE(V_CLIENTS)))
WHERE CONTRACT_ORDER = 2) CANDIDATE_CONTRACT
ON (CONTRACTS.CONTRACTID = CANDIDATE_CONTRACT.CONTRACTID)
WHEN MATCHED THEN UPDATE SET CONTRACTS.ENDDATE = CANDIDATE_CONTRACT.ENDDATE
WHERE CONTRACTS.ENDDATE IS NULL OR CONTRACTS.ENDDATE > CANDIDATE_CONTRACT.ENDDATE;
END AFTER STATEMENT;
END CONTRACT_ENDDATE_ADJUSTER;
/
After repeating the above inserts, the result is the same:
CONTRACTID CLIENTID STARTDATE ENDDATE
Break-Ring 1 11-MAY-56 18-FEB-57
GoBackHome 1 19-FEB-57 02-MAY-57
Gardening 1 03-MAY-57
SaveGalaxy 2 15-JUN-77 14-NOV-80
DefendHoth 2 15-NOV-80 08-MAR-83
GoWedding 2 09-MAR-83

Oracle Insert all data from another table with one column as null

I have two tables A and B both same structure except B has one addition extra column. I need to Retain all data from A in B but the extra column should set as null. How to do this. Please help.
Table A:
id VARCHAR2(64) NOT NULL,
effectiveDate DATE,
endDate DATE,
startDate DATE,
Type NUMBER(9),
salary NUMBER(19,3),
baseSalary NUMBER(19,3),
Amount NUMBER(19,3),
Amount1 NUMBER(19,3),
currency NUMBER(9),
Percentage NUMBER(20,9),
Salary NUMBER(19,3)
Table B
id VARCHAR2(64) NOT NULL,
effectiveDate DATE,
endDate DATE,
startDate DATE,
Type NUMBER(9),
salary NUMBER(19,3),
baseSalary NUMBER(19,3),
Amount NUMBER(19,3),
Amount1 NUMBER(19,3),
currency NUMBER(9),
Percentage NUMBER(20,9),
Salary NUMBER(19,3),
Notional NUMBER(9) -- This is the new column need to set as null
Thanks in advance.
insert
into tableB(
id, effectiveDate, endDate
,startDate, Type, salary
,baseSalary, Amount, Amount1
,currency, Percentage, Salary
,Notional
)
select id, effectiveDate, endDate
,startDate, Type, salary
,baseSalary, Amount, Amount1
,currency, Percentage, Salary
,null
from tableA;

How to create a view

I was trying to create a view with information of latest hired employee in each branch. But i was not succeed in that. Can anyone direct me towards the right path.
CREATE TABLE BRANCH(
BRANCH_ID NUMBER(8) PRIMARY KEY,
BRANCH_NAME VARCHAR2(100) NOT NULL,
SCHEDULE_LINK_NUM NUMBER(8),
MAIN_BRANCH_ID number(8),
BRANCH_MGR_ID NUMBER(8),
BRANCH_OPEN_DATE DATE,
EMAIL VARCHAR2(50),
URL VARCHAR2(50)
);
CREATE TABLE EMPLOYEE(
EMPLOYEE_ID NUMBER(8) PRIMARY KEY,
FIRST_NAME VARCHAR2(50),
LAST_NAME VARCHAR2(50),
MIDDLE_NAME VARCHAR2(50),
GENDER CHAR(1),
SSN NUMBER(9) NOT NULL,
DOB DATE,
MARITAL_STATUS VARCHAR2(30),
SPOUSE_NAME VARCHAR2(50),
HOME_PHONE NUMBER(10),
CELL_PHONE NUMBER(10),
OFFICE_PH_EXTN NUMBER(6),
EMPLOYEE_TYPE VARCHAR2(40),
SALARY NUMBER(10,2),
TAX_DEDUCTION NUMBER(10,2),
BRANCH_ID NUMBER(8),
MGR_ID NUMBER(8),
CONSTRAINT EMP_BRANCH_FKEY FOREIGN KEY(BRANCH_ID) REFERENCES BRANCH(BRANCH_ID),
CONSTRAINT EMP_EMPTYPE_CHECK CHECK(EMPLOYEE_TYPE IN ('MANAGER', 'MECHANIC', 'SECRETARY', 'SALES PERSON')),
CONSTRAINT EMP_MARITSTATUS_CHECK CHECK(MARITAL_STATUS IN ('SINGLE', 'MARRIED', 'DIVORCED'))
);
CREATE TABLE EMP_WORK_HISTORY(
BRANCH_EMP_NUM NUMBER(8) PRIMARY KEY,
BRANCH_ID NUMBER(8),
EMPLOYEE_ID NUMBER(8),
JOIN_DATE DATE NOT NULL,
RELIEVING_DATE DATE,
EMPLOYEE_TYPE VARCHAR2(40),
DESCRIPTION VARCHAR2(200),
CONSTRAINT BRANCH_WRKHIS_BID_FKEY FOREIGN KEY(BRANCH_ID) REFERENCES BRANCH(BRANCH_ID),
CONSTRAINT BRANCH_WRKHIS_EID_FKEY FOREIGN KEY(EMPLOYEE_ID) REFERENCES EMPLOYEE(EMPLOYEE_ID),
CONSTRAINT EMP_WRKHIS_EMPTYPE_CHECK CHECK(EMPLOYEE_TYPE IN ('MANAGER', 'MECHANIC', 'SECRETARY', 'SALES PERSON'))
);
I have written the view like below:
CREATE VIEW LAST_EMPLOYEE_BRANCH AS
WITH LAST_EMP_BRANCH AS
(SELECT MAX(EWH.JOIN_DATE) AS LAST_HIRED_DATE, EWH.BRANCH_ID
FROM EMP_WORK_HISTORY EWH GROUP BY EWH.BRANCH_ID)
SELECT E.FIRST_NAME || E.LAST_NAME AS EMPLOYEE_NAME,
B.BRANCH_NAME, LEB.LAST_HIRED_DATE, E.SALARY,
EXTRACT(YEAR FROM NUMTOYMINTERVAL(MONTHS_BETWEEN(TRUNC(SYSDATE),E.DOB),'MONTH')) AS AGE
FROM EMPLOYEE E, BRANCH B, LAST_EMP_BRANCH LEB
WHERE E.BRANCH_ID = B.BRANCH_ID
AND LEB.BRANCH_ID = E.BRANCH_ID;
By running the above view i am getting all employees records. Can anyone help on this?
Looks like you forgot to include the EMP_WORK_HISTORY table and the LAST_HIRED_DATE column in the join. Try the query below:
CREATE OR REPLACE VIEW LAST_EMPLOYEE_BRANCH AS
WITH LAST_EMP_BRANCH AS
(SELECT MAX(EWH.JOIN_DATE) AS LAST_HIRED_DATE, EWH.BRANCH_ID
FROM EMP_WORK_HISTORY EWH GROUP BY EWH.BRANCH_ID)
SELECT E.FIRST_NAME || E.LAST_NAME AS EMPLOYEE_NAME,
B.BRANCH_NAME, LEB.LAST_HIRED_DATE, E.SALARY,
EXTRACT(YEAR FROM NUMTOYMINTERVAL(MONTHS_BETWEEN(TRUNC(SYSDATE),E.DOB),'MONTH')) AS AGE
FROM EMPLOYEE E, BRANCH B, LAST_EMP_BRANCH LEB, EMP_WORK_HISTORY EWH
WHERE E.BRANCH_ID = B.BRANCH_ID
AND LEB.BRANCH_ID = E.BRANCH_ID
AND E.EMPLOYEE_ID = EWH.EMPLOYEE_ID
AND B.BRANCH_ID = EWH.BRANCH_ID
AND LEB.LAST_HIRED_DATE = EWH.JOIN_DATE;

How to update 2 tables using triggers

I have 2 tables,
lv_data,
It has the following fields,
emp_name tot_days
guru 18
leave_data
it has the following fields,
emp_name From_date to_date no_of_days remaining_days
guru 02/05/2012 03/05/2012 2
In second table if the data is inserted, the no_of_days will be automatically calculated (from to_date - From_date)+1
Here I need to write the trigger to update the remaining_days column,
In first table for all emp_name, tot_days is 18 days, so in second table whenever the record is inserted, the remaining_days should be calculated like this
remaining_days := tot_days - no_of_days
And this(calculated) value should be updated in tot_days column in first table(lv_data),
Sample Example:
emp_name tot_days
guru 18
leave_data
emp_name From_date to_date no_of_days remaining_days
guru 02/05/2012 03/05/2012 2 16
Now the first table should be updated like,
emp_name tot_days
guru 16
So I need to update 2 tables. Can someone help me to update these 2 tables through trigger?
Have an before insert trigger on the table which will set the record before inserting it
Few things to note:
Your data model doesn't have a unique identifier for a row
I don't think your "no_of_days" calculation is right.
CREATE OR replace TRIGGER leave_data_before_insert
BEFORE INSERT ON LEAVE_DATA
FOR EACH ROW
DECLARE
CURSOR c_lv_data(
p_emp_id IN lv_data.id%TYPE) IS
SELECT tot_days
FROM lv_data
WHERE id = p_emp_id;
v_tot_days NUMBER;
BEGIN
OPEN c_lv_data(:new.id);
FETCH c_lv_data INTO v_tot_days;
:new.no_of_days := ( :new.from_date - :new.TO_DATE ) + 1;
:new.remaining_days := v_tot_days - :new.no_of_days;
UPDATE lv_data
SET tot_days = :new.remaining_days
WHERE id = :new.id;
CLOSE c_lv_data;
END;
DDL used to test:
CREATE TABLE lv_data
(
id NUMBER,
emp_name VARCHAR2(240),
tot_days NUMBER
);
CREATE TABLE leave_data
(
id NUMBER,
emp_name VARCHAR2(240),
from_date DATE,
to_date DATE,
no_of_days NUMBER,
remaining_days NUMBER
);
DML used to test:
INSERT INTO lv_data
VALUES (1,
'sathya',
18);
INSERT INTO LEAVE_DATA
VALUES ('1',
'sathya',
SYSDATE,
SYSDATE + 2,
NULL,
NULL);

Resources