Using Procedure in Trigger in PL/SQL - oracle

Well I have this Procedure:
SET SERVEROUTPUT ON;
CREATE OR REPLACE PROCEDURE check_salary (job_id employees.job_id%TYPE, salary employees.salary%TYPE)
IS
maxSal NUMBER;
minSal NUMBER;
BEGIN
SELECT MAX(salary) INTO maxSal FROM employees WHERE job_id = job_id;
SELECT MIN(salary) INTO minSal FROM employees WHERE job_id = job_id;
IF maxSal >= salary OR minSal <= salary THEN
RAISE_APPLICATION_ERROR(-20001,'Invalid slary '||salary||'. Salaries for job '||job_id||' must be between '||minSal||' and '||maxSal);
END IF;
END;
This PROCEDURE has two parameters. It checks if the salary of a job_id is between the max and the min of the job.
Now I want to create a TRIGGER.
If INSERT or UPDATE is called on employees I want to execute the prodcedure. But I don't know what I should write as a parameter in the procedure
CREATE OR REPLACE TRIGGER check_salary_trg
BEFORE INSERT OR UPDATE ON employees
FOR EACH ROW
DECLARE
BEGIN
check_salary(); --Don't know which parameter I should use
END;

You should use :NEW as New Row and :OLD as Old Row.
But I think it is not useful to create a trigger as BEFORE INSERT.
You may create a trigger as AFTER INSERT OR UPDATE.
Here is an example :
CREATE OR REPLACE TRIGGER check_salary_trg
AFTER INSERT OR UPDATE ON EMPLOYEE
REFERENCING NEW AS New OLD AS Old
FOR EACH ROW
DECLARE
BEGIN
check_salary(:NEW.job_id);
EXCEPTION
WHEN OTHERS THEN
-- Consider logging the error and then re-raise
RAISE;
END check_salary_trg;

You just need to add the job_id and the salary
CREATE OR REPLACE TRIGGER check_salary_trg
BEFORE INSERT OR UPDATE ON employees
FOR EACH ROW
DECLARE
BEGIN
check_salary(:new.job_id, :new.salary);
END;

Related

Why doesn't this PL/SQL trigger show any result?

I need to write a trigger that outputs the first name and last name of employees whose salary have been modified. This trigger will work when the old salary of the employee was less than 10,000 and with the modification, it's bigger than 10,000. This trigger has to be a row trigger
I have written this:
CREATE OR REPLACE TRIGGER print_info
AFTER UPDATE OF salary ON employees
FOR EACH ROW
DECLARE fname employees.first_name%type; lname employees.last_name%type;
BEGIN
IF(:OLD.salary < 10000 AND :NEW.salary > 10000) THEN
dbms_output.put('fname, lname');
END IF;
END;
/
This code compiles and the trigger is created successfully, but when I update an employee's salary, within the trigger requirements, the trigger doesn't execute or doesn't show me anything.
Am I doing something wrong here?
Thanks for your help.
Just add dbms_output.new_line; after the dbms_output.put or use dbms_output.put_line
CREATE OR REPLACE TRIGGER print_info
AFTER UPDATE OF salary ON employees
FOR EACH ROW
DECLARE fname employees.first_name%type; lname employees.last_name%type;
BEGIN
IF(:OLD.salary < 10000 AND :NEW.salary > 10000) THEN
dbms_output.enable;
dbms_output.put('fname, lname '||:NEW.first_name||','||:NEW.last_name);
dbms_output.new_line;
END IF;
END;

Set a column value equal to another column with a trigger in Oracle

I have two columns, Id and Descrizione.
I want to set id = descrizione when a user insert a form. How can i do this with a trigger?
I've tried this but it not works
create or replace TRIGGER RUOLI_ID
BEFORE INSERT ON ruoli
FOR EACH ROW
BEGIN
IF :new.id IS NULL THEN
SET :new.id = Descrizione;
END IF;
END;
Close!
CREATE OR REPLACE TRIGGER ruoli_id
BEFORE INSERT
ON ruoli
FOR EACH ROW
BEGIN
:new.id := NVL (:new.id, :new.descrizione);
END;
You can use the WHEN clause which will execute the trigger only when ID is null, as follows:
CREATE OR REPLACE TRIGGER RUOLI_ID
BEFORE INSERT ON RUOLI
FOR EACH ROW
WHEN (NEW.ID IS NULL)
BEGIN
:NEW.ID := :NEW.DESCRIZIONE;
END;
Cheers!!

Difficulty compiling an AFTER INSERT OR UPDATE trigger

I have an EMPLOYEE table with SALARY field. I'm using Oracle SQL developer. I want to write a trigger so that when someone update salary in EMPLOYEE table, it will update Salary field in EMPLOYEE_SALARIES table as low, medium, high. Here's the second table.
CREATE TABLE Employee_Salaries(
Ssn CHAR(9) NOT NULL,
Salary VARCHAR(10),
Log_Date DATE
);
Here's the trigger and procedure to update the Salary field to low, middle or high.
CREATE OR REPLACE PROCEDURE salaryType(x IN NUMBER, y OUT VARCHAR) IS
BEGIN
IF x >= 60000 THEN y := 'HIGH';
ELSIF (x >= 40000 AND x <= 60000) THEN y := 'MEDIUM';
ELSE y := 'LOW';
END IF;
END salaryType;
/
I get compiler error on this trigger. Please tell me what I did wrong or am I missing something.
CREATE OR REPLACE TRIGGER salary1
AFTER INSERT OR UPDATE ON Employee
FOR EACH ROW
BEGIN
DECLARE
salaryRank VARCHAR(10) := ' ';
salaryType(:new.Salary, salaryRank);
INSERT INTO Employee_Salaries(Ssn, Salary, Log_Date) VALUES (:new.Ssn, salaryRank, SYSDATE);
END;
/
Declaration Part is at wrong place(should be before BEGIN and just after FOR EACH ROW statement of TRIGGER's header), Make it as the following :
CREATE OR REPLACE TRIGGER salary1
AFTER INSERT OR UPDATE ON Employee
FOR EACH ROW
DECLARE
salaryRank VARCHAR(10) := ' ';
BEGIN
salaryType(:new.Salary, salaryRank);
INSERT INTO Employee_Salaries(Ssn, Salary, Log_Date) VALUES (:new.Ssn, salaryRank, SYSDATE);
END;
The keyword BEGIN in the trigger is in the wrong place. It should come after the DEFINE block; that is, after you declare salaryrank and before you invoke the procedure.

Mutating table error thrown from stored procedure fired by an after insert trigger

I have a requirement to call a stored procedure via 'after insert' trigger whenever data is inserted into table but I run into "error ORA-04091: table TEST.EMP is mutating, trigger/function may not see it". I understand the reason behind this error but how can I overcome this through Compound Triggers without disturbing the procedure?
create TABLE emp(
id NUMBER(4),
emp_name VARCHAR2(30),
dept_name VARCHAR2(10));
create or replace PROCEDURE emp_count(dept_name_v emp.dept_name%TYPE) as
DECLARE
dept_emp_count NUMBER(4) := 0;
BEGIN
SELECT count(*) INTO dept_emp_count FROM emp WHERE dept_name = dept_name_v;
UPDATE dept_stat SET d_emp_count = dept_emp_count WHERE dept_name = dept_name_v;
END;
create or replace TRIGGER dept
AFTER INSERT ON emp
FOR EACH ROW
BEGIN
emp_count(:NEW.dept_name);
END;
There is an example in documentation how to create a compound trigger: http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#CHDFEBFJ
Just change a few identifiers and declarations in this example, and you will get a trigger for your case:
CREATE OR REPLACE TRIGGER some_trigger
FOR INSERT ON emp
COMPOUND TRIGGER
TYPE dept_names_t IS TABLE OF emp.dept_name%TYPE INDEX BY SIMPLE_INTEGER;
dept_names dept_names_t;
idx SIMPLE_INTEGER := 0;
-- AFTER EACH ROW Section:
AFTER EACH ROW IS
BEGIN
idx := idx + 1;
dept_names(idx) := :NEW.dept_name;
END AFTER EACH ROW;
AFTER STATEMENT IS
BEGIN
FOR j IN 1..idx
LOOP
emp_count(dept_names(j));
END LOOP;
END AFTER STATEMENT;
END;
/

an Easy Oracle Trigger amendment

I found a trigger in our Oracle Database
create or replace trigger pii_user_activation_trigger
before insert on pii_user_activation
for each row
begin
select seq_pii_user_activation.nextval
into :new.id
from dual;
end;
I don't want the trigger to automatically generate the id each time a row is inserted. How can I modify the trigger so that it only generates a new id if the INSERT statement does not provide a value?
create or replace trigger pii_user_activation_trigger
before insert on pii_user_activation<
for each row
begin
IF :new.id IS NULL THEN
select seq_pii_user_activation.nextval
into :new.id
from dual;
END IF;
end;
It sounds like you just want
create or replace trigger pii_user_activation_trigger
before insert on pii_user_activation
for each row
begin
IF( :new.id IS NULL )
THEN
select seq_pii_user_activation.nextval
into :new.id
from dual;
END IF;
end;
This makes the generally reasonable assumption that there is no non-NULL default value specified for the column.
Just another method:
create or replace trigger pii_user_activation_trigger
before insert on pii_user_activation
for each row
WHEN (NEW.id IS NULL)
begin
select seq_pii_user_activation.nextval
into :new.id
from dual;
end;
(note that in a WHEN clause, you don't include the : before the NEW.

Resources