"PLS-00103: Encountered the symbol "EXCEPTION" when expecting - oracle

Trigger code -
CREATE OR REPLACE TRIGGER tib_ms_merchant_group
BEFORE INSERT
ON ms_merchant_group FOR EACH ROW DECLARE integrity_error EXCEPTION;
PRAGMA EXCEPTION_INIT (integrity_error, -20001);
errno INTEGER;
errmsg CHAR(200);
dummy INTEGER;
FOUND BOOLEAN;
BEGIN
-- Errors handling
EXCEPTION
WHEN integrity_error THEN
raise_application_error(errno, errmsg);
END;
Error -
"PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
:= . ( # % ;
The symbol ";" was substituted for "EXCEPTION" to continue."

Probably you should declare some content after the BEGIN directive to make the function do something actual? This is (probably) demanded by the SQL syntax. That is why EXCEPTION cant be put straight after BEGIN

As #sanfor said, you need to have something between the BEGIN-EXCEPTION block. I could compile the trigger -
SQL> CREATE
2 OR
3 replace TRIGGER tib_ms_merchant_group BEFORE
4 INSERT
5 ON emp FOR EACH ROW DECLARE integrity_error EXCEPTION;
6
7 PRAGMA EXCEPTION_INIT (integrity_error, -20001);
8 errno INTEGER;
9 errmsg CHAR(200);
10 dummy INTEGER;
11 FOUND BOOLEAN;
12 BEGIN
13 NULL;
14 EXCEPTION
15 WHEN integrity_error THEN
16 raise_application_error(errno, errmsg);
17 END;
18 /
Trigger created.
SQL> sho err
No errors.
SQL>
Just replace the table name and add the required trigger logic after BEGIN.

Related

Execute PROCEDURE on Oracle PL/SQL with DECLARE variable

I just currently learning about Oracle PL/SQL. I wanna create store procedure with variable and then call it with another script. Is it possible?
I tried use simple script without variable and it works:
CREATE OR REPLACE PROCEDURE testmyproc AS
BEGIN
INSERT INTO tes_table(dt)
VALUES (sysdate);
commit;
END testmyproc;
Then I call it with another script abc.sql
begin
testmyproc;
end;
It works successfully.
But, unfortunately if I use DECLARE (variable) at my PROCEDURE, it show error when I execute (but it success in create procedure).
Here's my PROCEDURE (no error):
CREATE OR REPLACE PROCEDURE sp_testmyproc AS
DECLARE
job_name varchar(100);
status_key number;
status_desc varchar(100);
notes varchar(250);
BEGIN
status_key := 1;
status_desc := 'SUCCESS';
notes := 'Process Completed';
INSERT INTO automation_log(job_name, dt, status_key, status_desc, notes)
VALUES (job_name, sysdate, status_key, status_desc, notes);
commit;
END sp_testmyproc;
Here's my execure script abc.sql (show error when i execute it)
-without DECLARE
begin
sp_testmyproc;
end;
-I tried to execute it with DECLARE
DECLARE
job_name varchar(100);
status_key number;
status_desc varchar(100);
notes varchar(250);
begin
status_key := 1;
status_desc := 'SUCCESS';
notes := 'Process Completed';
sp_testmyproc;
end;
It show error like this:
> ORA-06550: line 8, column 11:
> PLS-00905: SP_TESTMYPROC is invalid
> ORA-06550: line 8, column 3:
> PL/SQL: Statement ignored
Can I call Procedure for another script? Is It best practice?
I just think PROCEDURE can be used for many cases (something like function in programming).
Thank you!
You need to learn the syntax of the procedure.
In Procedure, You should not use the keyword DECLARE. Any variables you want to declare must be between AS and BEGIN in the procedure.
Your procedure should look like follows:
CREATE OR REPLACE PROCEDURE sp_testmyproc AS
--DECLARE
job_name varchar(100);
status_key number;
status_desc varchar(100);
notes varchar(250);
BEGIN
status_key := 1;
.....
.....
.....
Refer to this document for the syntax of the oracle procedure as it is very easy to follow.
Please note the difference when creating a stored procedure in SQL*Plus:
SQL> create or replace procedure test_ok as
2 v number;
3 begin
4 v:=0;
5 end;
6 /
Procedure created.
SQL> show errors
No errors.
SQL> create or replace procedure test_ko as
2 declare
3 v number;
4 begin
5 v:=0;
6 end;
7 /
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TEST_KO:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/1 PLS-00103: Encountered the symbol "DECLARE" when expecting one of
the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior external language
SQL>
If you have compilation errors you get at least Warning: Procedure created with compilation errors. If you have compilation errors and use show errors you get all error messages.

logging line number in oracle

I'm currently working on logging errors in a procedure. The goal of this procedure is to be called upon in exception handlers in the other packages in the DB and log the errors that each program encounters. below is my code.
CREATE OR REPLACE PROCEDURE APMS.test_procedure AS
procedure write_error_log (errcode number, errstr varchar2) is
pragma autonomous_transaction;
-- this procedure stays in its own new private transaction
begin
INSERT INTO error_log
(ora_err_tmsp,
ora_err_number,
ora_err_msg,
ora_err_line_no)
values (CURRENT_TIMESTAMP,
errcode,
errstr,
'line number');
COMMIT; -- this commit does not interfere with the caller's transaction.
end write_error_log;
BEGIN
INSERT INTO mockdata
VALUES ('data1', 'mockname', 'mockcity');
exception when others then
write_error_log(sqlcode,sqlerrm);
raise;
END test_procedure;
/
I'm currently just inducing an error in my mock_data table to log the error in the error_log table and see if its functional I just cant figure out how to log the line number column. I'm a complete beginner so any help would appreciated. Addiotionally, If anybody knows how I would be able to use this procedure in other packages/procedures to log the errors in other packages that would be awesome as well. I'm here to learn so any feedback is appreciated, I can further expand on this post if i'm not being clear.
Try using DBMS_UTILITY.FORMAT_ERROR_BACKTRACE. You can look here for more information.
Something like this should make works your code:
CREATE OR REPLACE PROCEDURE APMS.test_procedure AS
procedure write_error_log (errcode number, errstr varchar2,errline varchar2) is
pragma autonomous_transaction;
-- this procedure stays in its own new private transaction
begin
INSERT INTO error_log
(ora_err_tmsp,
ora_err_number,
ora_err_msg,
ora_err_line_no)
values (CURRENT_TIMESTAMP,
errcode,
errstr,
errline);
COMMIT; -- this commit does not interfere with the caller's transaction.
end write_error_log;
BEGIN
INSERT INTO mockdata
VALUES ('data1', 'mockname', 'mockcity');
exception when others then
write_error_log(sqlcode,sqlerrm,DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
raise;
END test_procedure;
Use the following to get the call stack:
dbms_utility.format_error_stack
dbms_utility.format_error_backtrace
For example,
SQL> declare
2 v1 integer := 1;
3 v2 integer := 0;
4 v3 integer;
5 procedure p1 (v1 in integer, v2 in integer, v3 out integer) is
6 begin
7 v3 := v1 / v2;
8 end;
9 procedure p2 (v1 in integer, v2 in integer, v3 out integer) is
10 begin
11 p1 (v1, v2, v3);
12 end;
13 begin
14 p2 (v1, v2, v3);
15 exception
16 when others then
17 dbms_output.put_line ('---------------------');
18 dbms_output.put_line ('This is what you record in log table:');
19 dbms_output.put (dbms_utility.format_error_stack);
20 dbms_output.put (dbms_utility.format_error_backtrace);
21 dbms_output.put_line ('---------------------');
22 raise;
23 end;
24 /
---------------------
This is what you record in log table:
ORA-01476: divisor is equal to zero
ORA-06512: at line 7
ORA-06512: at line 11
ORA-06512: at line 14
---------------------
declare
*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at line 22

Exclude Extra Error Information from RAISE_APPLICATION_ERROR

I have raised an error message in a PL/SQL trigger and it works fine except that it returns more than the error I specify to the application. In addition to the custom error I get information about the line that the error happened on and the trigger.
For example it will get
ORA-20111: There is a custom error here
ORA-06512: at "{schema_name}.{trigger_name}", LINE 2
ORA-04088: error during execution of trigger {schema_name}.{trigger_name}<br>
.Operation canceled.
What I actually want is:
ORA-20111: There is a custom error here
How do I remove the extra information from the error message before it is returned to my application? My testing code below...
CREATE OR REPLACE TRIGGER CUSTOM_ERROR
BEFORE INSERT OR UPDATE ON {SCHEMA_NAME}.{TABLE_NAME} FOR EACH ROW
BEGIN
RAISE_APPLICATION_ERROR(-20111, 'There is a custom error here');
END;
You could use RAISE_APPLICATION_ERROR.
For example,
SQL> DECLARE
2 custom_err EXCEPTION;
3 PRAGMA EXCEPTION_INIT( custom_err, -20099 );
4 BEGIN
5 raise_application_error( -20099, 'This is a custom error' );
6 EXCEPTION
7 WHEN custom_err THEN
8 dbms_output.put_line( sqlerrm );
9 END;
10 /
ORA-20099: This is a custom error
PL/SQL procedure successfully completed.
SQL>
PRAGMA EXCEPTION_INIT is to give a custom error number, which could vary in a range from -20001 to -20999
However, you need to take care of the already-defined exceptions from being raised.
For example,
SQL> DECLARE
2 custom_err EXCEPTION;
3 PRAGMA EXCEPTION_INIT( custom_err, -20099 );
4 v number;
5 BEGIN
6 SELECT empno INTO v FROM emp WHERE empno = 1234;
7 raise_application_error( -20099, 'This is a custom error' );
8 EXCEPTION
9 WHEN custom_err THEN
10 dbms_output.put_line( sqlerrm );
11 END;
12 /
DECLARE
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 6
SQL>
There is a NO_DATA_FOUND exception thrown. You could suppress that, however, it will leave the error stack with additional messages.
SQL> DECLARE
2 custom_err EXCEPTION;
3 PRAGMA EXCEPTION_INIT( custom_err, -20099 );
4 v number;
5 BEGIN
6 SELECT empno INTO v FROM emp WHERE empno = 1234;
7 raise_application_error( -20099, 'This is a custom error' );
8 EXCEPTION
9 WHEN no_data_found THEN
10 raise_application_error( -20099, 'This is a custom error' );
11 WHEN custom_err THEN
12 dbms_output.put_line( sqlerrm );
13 END;
14 /
DECLARE
*
ERROR at line 1:
ORA-20099: This is a custom error
ORA-06512: at line 10
SQL>
I would always want to log the errors as verbose as possible. The raise_application_error is good for a custom message to be displayed on the application, however, I would log all the errors in the program.
Please have a look at:
dbms_utility.format_error_stack
dbms_utility.format_error_backtrace

What exact exception to be caugth while calling TO_DATE in pl/sql code

I have below code to_date('1311313', 'yymmdd') which actually throws exception with saying invalid month. Which is can manage as
exception
when others then
sop('date format is wrong');
Here the problem is everything will get caught which I do not want to do as if some other error will occur then also it will pass the message date format is wrong. I also do not want to create a user defined exception. Just want to know which exception is being thrwon out so that I can use in my code like below
exception
when name_of_exception then
sop('date format is wrong');
The Internally Defined Exceptions section of the Oracle Database PL/SQL Language Reference says:
An internally defined exception does not have a name unless either PL/SQL gives it one (see "Predefined Exceptions") or you give it one.
You code throws the exception ORA-01830:
SQL> select to_date('1311313', 'yymmdd') from dual
*
ERROR at line 1:
ORA-01830: date format picture ends before converting entire input string
Since it is not one of the Predefined Exceptions, you must give it a name yourself:
declare
ex_date_format exception;
pragma exception_init(ex_date_format, -1830);
v_date date;
begin
select to_date('1311313', 'yymmdd')
into v_date
from dual;
exception
when ex_date_format then
sop('date format is wrong');
end;
/
There are at least two approaches to handle different exceptions raised during an attempt to convert character literal to a value of DATE data type:
Define as many exception names and associate them with Oracle error codes, using exception_init pragma, as many exceptions to_date() function is able to raise.
Create a stand alone, or part of a package, wrap-up function for to_date() function, with one when others exception handler.
Personally I lean toward the second one.
SQL> create or replace package util1 as
2 function to_date1(
3 p_char_literal in varchar2,
4 p_date_format in varchar2
5 ) return date;
6 end;
7 /
Package created
SQL> create or replace package body util1 as
2
3 function to_date1(
4 p_char_literal in varchar2,
5 p_date_format in varchar2
6 ) return date is
7 begin -- in this situation it'll be safe to use `when others`.
8 return to_date(p_char_literal, p_date_format);
9 exception
10 when others then
11 raise_application_error(-20001, 'Not a valid date');
12 end;
13
14 end;
15 /
Package body created
Now, there is only one exception to handle, -20001 Not a valid date, and your PL/SQl block might look like this:
SQL> set serveroutput on;
-- [1] otherwise, for '1311313' the ORA-01830 exception would be raised
SQL> declare
2 not_a_valid_date exception;
3 pragma exception_init(not_a_valid_date, -20001);
4 l_res date;
5 begin
6 l_res := util1.to_date1('1311313', 'yymmdd');
7 exception
8 when not_a_valid_date then
9 dbms_output.put_line(sqlerrm);
10 -- or other handler sop('date format is wrong');
11 end;
12 /
ORA-20001: Not a valid date
-- [2] otherwise, for '000000' the ORA-01843(not a valid month)
-- exception would be raised
SQL> declare
2 not_a_valid_date exception;
3 pragma exception_init(not_a_valid_date, -20001);
4 l_res date;
5 begin
6 l_res := util1.to_date1('000000', 'yymmdd');
7 exception
8 when not_a_valid_date then
9 dbms_output.put_line(sqlerrm);
10 -- or other handler sop('date format is wrong');
11 end;
12 /
ORA-20001: Not a valid date

Where oracle Stores user defined exceptions?

Is there oracle table that stores user defined exceptions?
No.
User-defined exceptions are, like other variables, defined in PL/SQL blocks and have whatever scope the PL/SQL variable would have. So, for example
DECLARE
my_exception EXCEPTION;
BEGIN
RAISE my_exception;
EXCEPTION
WHEN my_exception
THEN
dbms_output.put_line( 'Caught my_exception' );
END;
will create the user-defined exception my_exception but the exception will only exist for the scope of the anonymous PL/SQL block. You can define exceptions in packages so that they can be referenced by multiple PL/SQL blocks. And you can use the exception_init pragma to associate user-defined exceptions with particular error codes
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 my_exception EXCEPTION;
3 pragma exception_init( my_exception, -20001 );
4 BEGIN
5 RAISE my_exception;
6* END;
SQL> /
DECLARE
*
ERROR at line 1:
ORA-20001:
ORA-06512: at line 5
Or you can use the raise_application_error function either alone or in concert with user-defined exception variables
SQL> ed
Wrote file afiedt.buf
1 DECLARE
2 my_exception EXCEPTION;
3 pragma exception_init( my_exception, -20001 );
4 BEGIN
5 RAISE_APPLICATION_ERROR( -20001, 'This is my error text' );
6 EXCEPTION
7 WHEN my_exception
8 THEN
9 dbms_output.put_line( 'Caught my_exception' );
10 dbms_output.put_line( sqlerrm );
11* END;
SQL> /
Caught my_exception
ORA-20001: This is my error text
PL/SQL procedure successfully completed.
There is no data dictionary table to store user-defined exceptions because there are so many (potentially conflicting) ways that your code might define those exceptions. From a good exception management standpoint, you would generally want to come up with a consistent way of defining your application-specific exceptions and sticking to that approach. Personally, I like a package that defines all my exceptions and associates them with error codes
SQL> ed
Wrote file afiedt.buf
1 create or replace package error_pkg
2 as
3 invalid_name exception;
4 pragma exception_init( invalid_name, -20001 );
5 invalid_address exception;
6 pragma exception_init( invalid_address, -20002 );
7* end;
SQL> /
Package created.
Assuming all my user-defined exceptions are all defined like this, I can go to the package definition for all my definitions.

Resources