Reputation: 1385
A similar question might have been asked, if so please share the link.
Required:
Whenever a new record is created or updated, a validation is required that the salary of the person is in range according to job.
Below is the trigger,
create or replace TRIGGER secure_employees_sal_range
BEFORE INSERT OR UPDATE OF salary,job_id ON employees
FOR EACH ROW
DECLARE
p_min_sal Integer;
p_max_sal Integer;
BEGIN
--check_salaray_range(employee_id,job_id,salary);
select min_salary, max_salary
into p_min_sal, p_max_sal
from jobs
where job_id = p_job_id;
if p_salary < p_min_sal OR p_salary > p_max_sal THEN
RAISE_APPLICATION_ERROR (-20225,
'Salray should in range' || p_min_sal || ' and ' || p_max_sal);
END IF;
END secure_employees_sal_range;
But I am getting error
Error at line 13: PL/SQL: Statement ignored
Line 14: where job_id = :new.job_id;
How can we set the value of p_job_id from employee table?
Update: Now getting the error message when the salary is out of range when creating a new employee
ORA-20225: Salray should in range4000 and 10000 ORA-06512: at "HR.SECURE_EMPLOYEES_SAL_RANGE", line 14 ORA-04088: error during execution of trigger 'HR.SECURE_EMPLOYEES_SAL_RANGE' Unable to process row of table EMPLOYEES.
And when trying to update an existing record then,
ORA-20505: Error in DML: p_rowid=215, p_alt_rowid=EMPLOYEE_ID, p_rowid2=, p_alt_rowid2=. ORA-20225: Salray should in range4000 and 10000 ORA-06512: at "HR.SECURE_EMPLOYEES_SAL_RANGE", line 14 ORA-04088: error during execution of trigger 'HR.SECURE_EMPLOYEES_SAL_RANGE' Unable to process row of table EMPLOYEES.
Upvotes: 1
Views: 2376
Reputation: 231661
Triggers don't have parameters.
My guess is that you want a row-level trigger, rather than the statement-level trigger that you have here. I'm guessing that within the row-level trigger that you'd want to use the :new.job_id
to look up the data in the jobs
table
create or replace TRIGGER secure_employees_sal_range
BEFORE INSERT OR UPDATE OF salary,job_id ON employees
FOR EACH ROW
DECLARE
p_min_sal Integer;
p_max_sal Integer;
BEGIN
--check_salaray_range(employee_id,job_id,salary);
select min_salary, max_salary
into p_min_sal, p_max_sal
from jobs
where job_id = :new.job_id;
if p_salary < p_min_sal OR p_salary > p_max_sal THEN
RAISE_APPLICATION_ERROR (-20225,
'Salary should in range' || p_min_sal || ' and ' || p_max_sal);
END IF;
END secure_employees_sal_range;
I'm assuming that this is a homework assignment. In reality, in a multi-user system, this sort of trigger has a variety of issues. For example, someone may be modifying the jobs
table at the same time that you're modifying the employees
table and neither transaction would be able to see the uncommitted work of the other. Even if you have a corresponding trigger on jobs
, it's entirely possible to end up with saved data that violates the range rule you're trying to enforce.
As a general rule, I would also suggest that local variables use the l_
prefix rather than p_
which generally denote parameters. I would also generally suggest that you use anchored types. So
l_min_sal jobs.min_salary%type;
That way, if the data type in the jobs
table changes, your code automatically adapts.
Upvotes: 2