PLSQL Trigger: before insert - oracle

Am trying to write a trigger which has to restrict for zero salary before insertion.
I have written but its not working. I am getting an error as trigger is invalid and failed re validation.
Code:
create or replace trigger emp_sal
before insert or update on employee
referencing new as new old as old
for each row
begin
if :new.salary<=0 then
raise_application_error (-20999,’salary is zero’);
end if;
end;
/
Please let me know where the problem is. Thank you

Your code is okay. The only problem I can imagine is that you were using the wrong character for the single quotes in ’salary is zero’.
Run show errors right after you created the trigger (assuming you're uning sqlplus)
But I agree with zerkms. This is a case for a check constraint.

Related

Mutating Trigger Error with Trigger in Oracle PL/SQL [duplicate]

I get an error (ORA-04091: table DBPROJEKT_AKTIENDEPOT.AKTIE is mutating, trigger/function may not see it) when executing my trigger:
CREATE OR REPLACE TRIGGER Aktien_Bilanz_Berechnung
AFTER
INSERT OR UPDATE OF TAGESKURS
OR INSERT OR UPDATE OF WERT_BEIM_EINKAUF
ON AKTIE
FOR EACH ROW
DECLARE
bfr number;
Begin
bfr := :new.TAGESKURS - :new.WERT_BEIM_EINKAUF;
UPDATE AKTIE
SET BILANZ = TAGESKURS - WERT_BEIM_EINKAUF;
IF bfr < -50
THEN
DBMS_OUTPUT.PUT_LINE('ACHTUNG: The value (Nr: '||:new.AKTIEN_NR||') is very low!');
END IF;
END;
I want to check the value "BILANZ" after calculating it, wether it is under -50.
Do you have any idea why this error is thrown?
Thanks for any help!
There are several issues here:
Oracle does not allow you to perform a SELECT/INSERT/UPDATE/DELETE against a table within a row trigger defined on that table or any code called from such a trigger, which is why an error occurred at run time. There are ways to work around this - for example, you can read my answers to this question and this question - but in general you will have to avoid accessing the table on which a row trigger is defined from within the trigger.
The calculation which is being performed in this trigger is what is referred to as business logic and should not be performed in a trigger. Putting logic such as this in a trigger, no matter how convenient it may seem to be, will end up being very confusing to anyone who has to maintain this code because the value of BILANZ is changed where someone who is reading the application code's INSERT or UPDATE statement can't see it. This calculation should be performed in the INSERT or UPDATE statement, not in a trigger. It considered good practice to define a procedure to perform INSERT/UPDATE/DELETE operations on a table so that all such calculations can be captured in one place, instead of being spread out throughout your code base.
Within a BEFORE ROW trigger you can modify the values of the fields in the :NEW row variable to change values before they're written to the database. There are times that this is acceptable, such as when setting columns which track when and by whom a row was last changed, but in general it's considered a bad idea.
Best of luck.
You are modifying the table with the trigger. Use a before update trigger:
CREATE OR REPLACE TRIGGER Aktien_Bilanz_Berechnung
BEFORE INSERT OR UPDATE OF TAGESKURS OR INSERT OR UPDATE OF WERT_BEIM_EINKAUF
ON AKTIE
FOR EACH ROW
DECLARE
v_bfr number;
BEGIN
v_bfr := :new.TAGESKURS - :new.WERT_BEIM_EINKAUF;
:new.BILANZ := v_bfr;
IF v_bfr < -50 THEN
Raise_Application_Error(-20456,'ACHTUNG: The value (Nr: '|| :new.AKTIEN_NR || ') is very low!');
END IF;
END;

Using trigger to check the data if already exist in the table and block the insertion

I am trying to use trigger to check whether whether the plate number that user is inserting already exist or not.If found then display message insertion blocked. There were some errors but i cant solve it. Below is the script:
CREATE OR REPLACE TRIGGER trig_check_plate_no
BEFORE INSERT OR UPDATE OF plate_number ON cars
FOR EACH ROW
WHEN(NEW.plate_number IS NOT NULL)
DECLARE
vn_count NUMBER(10);
BEGIN
SELECT COUNT(*)
INTO vn_count
FROM cars
WHERE plate_number = NEW.plate_number
IF(:vn_count>0)
THEN DBMS_OUTPUT.PUT_LINE('Insertion blocked.');
ELSE DBMS_OUTPUT.PUT_LINE('Data inserted.');
END IF;
END trig_check_plate_no;
/
How can i solve it?
In fact, you can't force a trigger to abort the operation that triggered its execution other than providing invalid values on purpose which is not a good style at all.
To achieve what you want to do, the easiest way would be to create a unique index on that table:
ALTER TABLE cars ADD CONSTRAINT c_plate_no UNIQUE ( plate_number );
Your DBMS should throw an error when you try to insert a value that already exists.
After doing so, you can omit your trigger entirely.

ORACLE PL/SQL Programming problems with trigger

Hi I got a problem running a trigger created using ORACLE PL/SQL programming. Basically, whenever there is an insertion with a location that does not exist in the database, I have to insert a new tuple into FEATURES table. Here's the Trigger -
CREATE OR REPLACE TRIGGER sightTrigger
AFTER INSERT
ON SIGHTINGS
FOR EACH ROW
DECLARE
x INTEGER;
BEGIN
SELECT COUNT(*)INTO x
FROM FEATURES
WHERE FEATURES.location = :NEW.location;
IF(x=0) THEN
RAISE APPLICATION ERROR(-20001, 'Warning: Insert into the SIGHTINGS ...');
INSERT INTO FEATUERS(LOCATION,CLASS,LATITUDE<LONGITUDE,MAP,ELEV)
VALUES(:NEW.location, 'UNKNOWN', null, null, null, null);
END IF;
END sightTrigger;
It compiled fine but I ran a simple query to test it -
INSERT INTO SIGHTINGS VALUES ('Douglas dustymaiden', 'Person A', 'Piute', TO_DATE('17­Feb­07', 'DD­MON­YY'));
And it gave me an error called -
"ORA-20001: Warning: Insert into the SIGHTINGS..." (What I wanted it)
"ORA-06512: at line 7"
"ORA-04088: error during execution of trigger"
Then the insertion into the FEATURES table didn't occur when I tested it. Please help.
As per documentation on raise_application_error:
When called, raise_application_error ends the subprogram and returns a user-defined error number and message to the application. The error number and message can be trapped like any Oracle error.
So, first do the other insert, then raise the error. However, if you raise an unhandled error in a trigger, that will roll back the entire transaction and any data modifications with it and the trigger will error. You may want to consider returning a message to the user in a different way.

Trigger in oracle SQL - Validation?

Hello guys I'm trying to create a trigger to validate some data, I've got a table called 'Events' and what I need to do create a trigger that will give me an error when you try to add an event in July.
CREATE OR REPLACE TRIGGER concert_trigger
AFTER INSERT ON CONCERT
WHEN (event_date = 'July')
BEGIN
ALTER TABLE CONCERT
ADD CONSTRAINT chk_CONCERT CHECK (event.date ='July')
END;
Here is the trigger that I have started that I think is the way to go but I'm not sure if this is right.
Thanks, Leprejohn
Since your classwork requires the use of a trigger you'd want to do something like
CREATE OR REPLACE TRIGGER CONCERT_BI
BEFORE INSERT ON CONCERT
FOR EACH ROW
BEGIN
IF TO_CHAR(EVENT_DATE, 'MON') = 'JUL' THEN
RAISE_APPLICATION_ERROR(-20666, 'No concerts can be scheduled in July');
END IF;
END CONCERT_BI;
Here I'm assuming that EVENT_DATE is an actual DATE instead of a character string; if that was a bad guess then change the comparison appropriately.

How to avoid Getting ORACLE Mutating trigger error

I created the trigger to update the oracle data base table after insert.
CREATE OR REPLACE TRIGGER Update_ACU
AFTER INSERT ON TBL_ACU
FOR EACH ROW
BEGIN
UPDATE TBL_ACU
SET CURRENCY = 'XXX'
WHERE ACCOUNT like '%1568';
END ;
I inserted record as
insert into TBL_ACU values('23','USD','1231568');
I am getting table ORACLE Mutating trigger error.
Please help me how to resolve this.
It would be better to use BEFORE INSERT trigger to do this.
Try like this,
CREATE OR REPLACE
TRIGGER update_acu
BEFORE INSERT ON tbl_acu
FOR EACH ROW
WHEN (NEW.ACCOUNT LIKE '%1568')
BEGIN
:NEW.currency := 'XXX';
END ;
Well, you cannot modify the table from the trigger if the trigger is called upon modification of that table. There are various solutions to this problem including an AFTER STATEMENT trigger and caching modifications in some collection defined in PL/SQL PACKAGE, howewer in your situation I'd rather change the body of your trigger to this:
BEGIN
IF :NEW.ACCOUNT LIKE '%1568' THEN
:NEW.CURRENCY := 'XXX';
END IF;
END;
You can use the :NEW and :OLD variables inside the trigger, which identify the new and old values of the record accordingly. Modifying values of the :NEW record will cause changes in data actually inserted to the database.

Resources