I am learning how to write user-defined exceptions inside trigger using Oracle 11g XE and seems the answer for this question serves as a good example:
create or replace trigger trig1
before update
of sal
on emp
for each row
when (new.sal < old.sal)
declare
user_xcep EXCEPTION;
PRAGMA EXCEPTION_INIT( user_xcep, -20001 );
begin
raise user_xcep;
end;
/
However, when I try this an update a record with a value of sal lower than the original value, I get the following error:
Error starting at line : 24 in command -
update emp set sal = 1100 where id = 1001
Error report -
ORA-20001:
ORA-06512: at "USER01.TRIG1", line 5
ORA-04088: error during execution of trigger 'USER01.TRIG1'
I found from the Internet that this means a runtime error in the trigger code. But where is the problem? As the above code is from an answer written in 2013, because I am using a new version of Oracle, making the original trigger not working anymore? How should I fix it?
This happened because you need to specify what happened? when the custom error occurs:
Create Or Replace Trigger trig1
Before Update Of sal On emp
For Each Row
When (Nvl(new.sal, 0) < Nvl(old.sal, 0))
Declare
user_xcep Exception;
Pragma Exception_Init(user_xcep, -20001);
Begin
dbms_output.put_line('test');
Raise user_xcep;
Exception
When user_xcep Then
dbms_output.put_line('-'||sqlcode||' - '||sqlerrm);
When Others Then
dbms_output.put_line(sqlerrm);
End;
This you can defined using the Exception clause, first the custom errors and then the system errors like NO_DATA_FOUND, TO_MANY_ROWS and finally the OTHERS errors that catch any other error that occurr inside the trigger.
If you need to stop the program you can use the Raise_Application_Error inside the custom exception:
Raise_Application_Error(sqlcode, 'Custom Error Message');
Related
So, I'm working on this project and I added the following trigger to check age eligibility.
create or replace TRIGGER AGEVALIDATION
BEFORE INSERT OR UPDATE ON RECIPIENT
FOR EACH ROW
BEGIN
IF (EXTRACT (YEAR FROM SYSDATE) - EXTRACT (YEAR FROM :NEW.DATE_OF_BIRTH)) < 12 THEN
raise_application_error(-20001,'VACCINE ELIGIBILITY AGE IS 12 AND ABOVE');
end if;
END;
The following trigger works but needs to handle the following errors. I need both ORA-06512 and ORA-6512 handled. Can anyone help me with this?
Error starting at line : 1 in command -
INSERT INTO RECIPIENT(RECIPIENT_ID,FIRST_NAME,LAST_NAME,DATE_OF_BIRTH,CONTACT_NUMBER,STREET_ADDRESS,CITY,ZIPCODE,GENDER)
VALUES(152,'Batman1','adams','23-OCT-2019',6172544372,'234 HUNTINGTON AVE','BOSTON','02115','MALE')
Error report -
ORA-20001: VACCINE ELIGIBILITY AGE IS 12 AND ABOVE
ORA-06512: at "APP_ADMIN.AGEVALIDATION", line 3
ORA-04088: error during execution of trigger 'APP_ADMIN.AGEVALIDATION'
The trigger does not quite do what you think as you can compare 2022-01-01 and 2010-12-31 and the difference between 2022 and 2010 is 12 years but between the dates is only 11 years and 1 day. You need to use MONTHS_BETWEEN to compare the entire date:
create or replace TRIGGER AGEVALIDATION
BEFORE INSERT OR UPDATE ON RECIPIENT
FOR EACH ROW
BEGIN
IF MONTHS_BETWEEN(SYSDATE, :NEW.DATE_OF_BIRTH) < 12*12 THEN
raise_application_error(-20001,'VACCINE ELIGIBILITY AGE IS 12 AND ABOVE');
END IF;
END;
/
fiddle
I need both ORA-06512 and ORA-6512 handled.
The trigger cannot "handle" those exceptions as nothing in the trigger would generate those exceptions. What you are probably seeing is part of the stack trace that is generated from your user-defined exception and can be ignored; however, you have not included the complete stack-trace in your question so it is difficult to be sure.
If something did need "handling" then you should do it from the code where you perform the INSERT and not in the trigger.
The exception you need to catch is the -20001 which is actually being raised. Something like:
DECLARE
excpUser_1 EXCEPTION;
EXCEPTION_INIT(excpUser_1, -20001);
BEGIN
UPDATE RECIPIENT SET DATE_OF_BIRTH = SYSDATE - 3650; -- ten years, more or less
EXCEPTION
WHEN excpUser_1 THEN
DBMS_OUTPUT.PUT_LINE('Caught excpUser_1');
END;
I need to update some code which uses dynamic sql and potentially could have duplicate column names in the columns of the insert statement.
So I wanted to handle this, ORA-00957: Duplicate Column name. This error does not get handled by the most generic "when others" in the exception block. If I make it test a unique constraint violation it does.
Following some test code:
create table animal (id number , animal_type number,
animal_name varchar2(20), constraint id primary key(id));
-----------------------------------------------------
begin
for i in 1.. 100 loop
insert into animal(id, animal_type, animal_name)
values(i,floor(dbms_random.value(1,30)),'animal'||i);
end loop;
end;
-----------------------------------------------------
DECLARE
-- e_duplicate_column exception;
-- pragma exception_init(e_duplicate_column,-957);
BEGIN
insert into animal(id, animal_name, animal_name)
values(1000003, 'animal 1000003', 'animal 1000003');
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLCODE);
dbms_output.put_line(SQLERRM);
END;
I was trying to get the codes here as the pragma wasn't working(i.e. arriving) either. But that's not happening if it doesn't even get to "when others".
Any insights are appreciated.
Cheers, Robbert
PS oracle 12C, tried on sqldeveloper and toad
Your test code does not use dynamic SQL, which is required to generate an ORA-00957 error. Without dynamic SQL, Oracle will throw the ORA-00957 when it compiles your block, which I think you are misinterpreting as Oracle actually running you block and skipping the exception handler.
Try this instead as a test (make sure you have DBMS output enabled in your client!):
DECLARE
-- e_duplicate_column exception;
-- pragma exception_init(e_duplicate_column,-957);
BEGIN
execute immediate q'[insert into animal(id, animal_name, animal_name) values(1000003, 'animal 1000003', 'animal 1000003')]';
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SQLCODE);
dbms_output.put_line(SQLERRM);
END;
-957
ORA-00957: duplicate column name
When I generate the SQL using PowerDesigner and run it in Oracle, it throws the error
Warning:Trigger creation with compilation errors
create trigger "tib_material_classify" before insert
on "material_classify" for each row
declare
integrity_error exception;
errno integer;
errmsg char(200);
dummy integer;
found boolean;
begin
-- column ""id"" uses sequence material_classify_seq;
select material_classify_seq.nextval into :new."id" from dual;
-- errors handling
exception
when integrity_error then
raise_application_error(errno, errmsg);
end;
When I issue show errors in Oracle, it says the following:
10/5 PL/SQL: SQL Statement ignored
10/12 PL/SQL: ORA-02289: sequence does not exist
What am I doing wrong?
The error message suggests that sequence material_classify_seq is missing. You can create the missing sequence with the following SQL statement:
Create Sequence material_classify_seq;
Before create trigger you need create sequnce
Create sequence material_classify_seq start with 1; after create trigger
SQL> Exec Dbms_Scheduler.stop_job('US_ALERT',true);
begin Dbms_Scheduler.stop_job('US_ALERT',true); end;
ORA-27466: internal scheduler error: 1870
ORA-06512: at "SYS.DBMS_ISCHED", line 227
ORA-06512: at "SYS.DBMS_SCHEDULER", line 674
ORA-06512: at line 1
Does anyone has any idea of what's going wrong here ?
Database : Oracle
Version : 12c
This error is caused by the stack being unwound by unhandled exceptions in pl/SQL code. Most likely the scheduler is executing a procedure with some bad code in it. (See http://www.techonthenet.com/oracle/errors/ora06512.php)
The first thing to do is drop the job
BEGIN
DBMS_SCHEDULER.DROP_JOB('myjob1');
END;
/
Then start investigating your stored procedure(s) and add in some exception handling.
For example you might have some pl/sql code as follows
DECLARE pe_ratio NUMBER(3,1);
BEGIN
SELECT price / earnings INTO pe_ratio FROM stocks WHERE symbol = 'XYZ'; -- might cause division-by-zero error
INSERT INTO stats (symbol, ratio) VALUES ('XYZ', pe_ratio); COMMIT;
End;
If this was called by your job it could result in a ora 06512. (You probably will need to add in some logging/traces into to your pl/SQL to narrow this down, the line numbers in the error messages you reported may also help)
Replace it with
DECLARE pe_ratio NUMBER(3,1);
BEGIN
SELECT price / earnings INTO pe_ratio FROM stocks WHERE symbol = 'XYZ'; -- might cause division-by-zero error
INSERT INTO stats (symbol, ratio) VALUES ('XYZ', pe_ratio);
COMMIT;
EXCEPTION -- exception handlers begin
WHEN ZERO_DIVIDE THEN -- handles 'division by zero' error
INSERT INTO stats (symbol, ratio) VALUES ('XYZ', NULL);
COMMIT; ...
WHEN OTHERS THEN -- handles all other errors
ROLLBACK;
END; -- exception handlers and block end here
No more unhandled exceptions should result in no more ora 06512 errors and therefore your job will stop when when requested.
Here's some good info on exception handling in oracle
https://docs.oracle.com/cd/A97630_01/appdev.920/a96624/07_errs.htm
Hope that helps.
IF l_value = 'FALSE' THEN
RAISE_APPLICATION_ERROR(-20299, 'some error message');
END IF;
This is part of table trigger. It should return me a error number and message, but when alert pops out it returns only message number. No 'some error message'. Whats wrong
Maybe the name RAISE_APPLICATION_ERROR is misleading for you. It will not pop up something onto your GUI. That you program yourself depending on what client you are using. Put you can use RAISE_APPLICATION_ERROR to create your own SQL errors on which you act upon.
Example
-- a example table
create table mytest (col_a number, col_b char(20));
-- a example trigger
CREATE OR REPLACE TRIGGER mytest_before
BEFORE UPDATE
ON mytest
FOR EACH ROW
DECLARE
BEGIN
if :new.col_a < 0 then
RAISE_APPLICATION_ERROR(-20299, 'negative value not allowed for column A');
end if;
END;
insert into mytest values (1,'hallo');
set serveroutput on
DECLARE
negative_value EXCEPTION; -- declare exception
PRAGMA EXCEPTION_INIT (negative_value, -20299); -- assign error code to exception
BEGIN
update mytest set col_a = -1 where col_b = 'hallo';
EXCEPTION
WHEN negative_value THEN -- handle exception
-- do whatever you need to do to bring the error to the user
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20299)));
END;
/
The above will bring you the output in SQL*Plus or SQL Developer of that sort.
table MYTEST created.
TRIGGER mytest_before compiled
1 rows inserted.
anonymous block completed
ORA-20299: negative value not allowed for column A
ORA-06512: at "DEMO.MYTEST_BEFORE", line 4
ORA-04088: error during execution of trigger 'DEMO.MYTEST_BEFORE
Instead of DBMS_OUTPUT.PUT_LINE you can do whatever you need to do to show the user whatever you want him to show.
The alert in your form has been raised by some trigger code on your form. Have a look at your ON-ERROR trigger - what code does it have?
You may need to augment it to show DBMS_ERROR_TEXT in the alert.