How to make Oracle error messages more verbose? - oracle

The message that drives me crazy is ORA-01008 - Not all variables bound.
Is there a way to know which one of the 42 possible variable names I have misspelled without staring at the monitor till my eyes pop out?
Update: I use ADO.NET to access the database. Perhaps it does lose some information in Oracle exceptions, as #Justin Cave has suggested. But I'm positive that the parameter name never appears even in SQL Plus.

In general, Oracle provides the line and column number of any errors, but it is up to the particular API you are using (unless you happen to be writing an OCI application, which is probably unlikely) as to whether and how those APIs are called. Since the answer is likely to end up being API-specific, what API are are you using and what does your code look like when the error occurs (i.e. JDBC, ODBC, OLE DB, etc)?
As an example, if I write a PL/SQL block with a misspelled variable name, SQL*Plus will report the line and column number of the error in addition to the error message. Many APIs, on the other hand, will just report the PLS-00201 error by default.
SQL> declare
2 i integer;
3 begin
4 j := 1;
5 end;
6 /
j := 1;
*
ERROR at line 4:
ORA-06550: line 4, column 3:
PLS-00201: identifier 'J' must be declared
ORA-06550: line 4, column 3:
PL/SQL: Statement ignored
Similarly, if you execute a SQL statement with an invalid variable name, SQL*Plus will get the column and line position and put a * under the offending character, i.e.
SQL> create table a( col1 number );
Table created.
SQL> insert into a( colN ) values ( 1 );
insert into a( colN ) values ( 1 )
*
ERROR at line 1:
ORA-00904: "COLN": invalid identifier
Most PL/SQL IDE's (TOAD, SQL Developer, etc.) will do something similar by interrogating the appropriate OCI APIs under the covers. Precisely how this is done, however, will depend on the API.

I don't know of any way to get Oracle to make the error more specific. Maybe some future version will improve this error message.
Instead of just staring at it, though, there are other things you can try. For example, convert each variable in the SQL statement to a literal one at a time, until the error goes away. If possible, generate the list of variable names instead of typing them manually.

Related

PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ; - Not sure what is wrong in code

I am trying to create trigger as below but getting error specified below. Can any one please help me to figure out what is wrong with the code. Thank you in advance
Code:
CREATE OR REPLACE EDITIONABLE TRIGGER TEST_DATA.IVR_SEQ
BEFORE INSERT ON TEST_DATA.TRANSACTION
FOR EACH ROW
BEGIN
SELECT TEST_DATA.IVR_SEQ.NEXTVAL
INTO :new.IVRID
FROM dual;
END;
/
Error:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ;
Tool: Oracle SQL Developer
Strange, as there's nothing wrong with it, but I get the same error as you do when executing it literally.
SQL> create or replace -- EDITIONABLE
2 trigger scott.trg_ivr_seq
3 before insert on scott.transaction
4 for each row
5 begin
6 select scott.ivr_seq.nextval
7 into :new.ivrid
8 from dual;
Warning: Trigger created with compilation errors.
SQL> show err trigger trg_ivr_Seq
Errors for TRIGGER TRG_IVR_SEQ:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/11 PLS-00103: Encountered the symbol "end-of-file" when expecting
one of the following:
;
(editionable is not an option in my 11gXE so I removed it).
As you can see, error points to line #4, column #11 which is
4 for each row
Rewritten from scratch (and "improved" a little bit):
SQL> create or replace trigger scott.ivr_seq
2 before insert on scott.transaction
3 for each row
4 begin
5 :new.ivrid := scott.ivr_seq.nextval;
6 end;
7 /
Trigger created.
SQL>
It works with select as well (just that you wouldn't think that it is wrong):
SQL> create or replace trigger scott.ivr_seq
2 before insert on scott.transaction
3 for each row
4 begin
5 select scott.ivr_seq.nextval
6 into :new.ivrid
7 from dual;
8 end;
9 /
Trigger created.
SQL>
So ... rewrite it. I don't see any garbage characters (in Notepad++), I have no idea what's wrong with it.
[EDIT]
Luke Woodward's comment made me do another test. Yes, Luke is right!
Comment in the 1st line, before actually stating what I'm creating causes an error:
SQL> create or replace -- comment
2 trigger trg_test
3 before insert on dept
4 for each row
5 begin
6 null;
Warning: Trigger created with compilation errors.
But, comment in the 1st line AFTER stating what's being created doesn't cause any errors:
SQL> create or replace trigger -- comment here
2 trg_test
3 before insert on dept
4 for each row
5 begin
6 null;
7 end;
8 /
Trigger created.
Thank you, Luke!
There are several ways you can get this error:
Your SQL is malformed, you are missing a ; somewhere
Not present in the provided snippet.
Your SQL is malformed, the parser is being tripped up and believes things to be things they are not, finally failing when it get to the end of the file.
Not obviously present in the provided snippet. However i can't test the EDITIONABLE clause as it is not present in my db version, so it may be introducing some addition required syntax.
Your interface is mangling the SQL before it sends it to the database to be compiled.
Unlikely as SQL developer is way better at not doing this than SQL*Plus was, but if you have any custom configuration there are all kinds of things that could be happening, check what is actually getting to the database by looking at trigger in the database and see if it matches what you expect to be there.
Invalid characters in your code
Not a common issue but can be eliminated by either retyping the trigger manually, not using copy paste, or by pasting from a know clean source. (copy/paste from the web can include lots of weird character replacements used to get the layout right in the browser (no-break spaces, etc.), and apps like word can mangle things like quotes (e.g.Word replaces ' ' with ‘ ’)
Code in the same file before the trigger definition that has errors.
I am assuming you have run this separately from any other code, but if not put this trigger create statement in its own file and run it there.
Scenario 2 is being triggered by a non obvious misparse of the code.
This could be caused by other objects in this or a different schema with identical names, keyword use, etc. and can depend on which schema is running the DDL statement.
Try quoting TEST_DATA.TRANSACTION as TEST_DATA."TRANSACTION", TRANSACTION is a keyword in oracle, and while some keywords can be used in some contexts, possibly your version of oracle is treating it as a keyword and messing up the rest of the parsing. This compiles fine on my DB without the quotes so i would lean more toward the next possibility, but I have this issue with a schema named "SEARCH" on my database, in some contexts you need to quote the name to prevent compile errors.
Check for name reuse on schemas, tables, views, etc. In your example your trigger and your sequence have the same name TEST_DATA.IVR_SEQ. On its own this is not an issue, but can cause seemingly random compile errors depending on where the duplication is.
I could not reproduce your specific compile error, but I was able to create a few different compile errors by creating different name collisions (example creating a table in the TEST_DATA schema named TEST_DATA, creating a function named TEST_DATA, creating a package, sequence named TEST_DATA, a function named IVR_SEQ in a package named TEST_DATA, etc.). It is possible on your version of Oracle this or a similar collision is creating the EOF error.

Object is invalid PLSQL Procedure

I use a dataset that has billing information:
Table Image
And I want to create a procedure that gives information about a specific bill by giving an invoice id
CREATE OR REPLACE PROCEDURE print_information(
invoiceID varchar(11);
) IS
p_smtable supermarket%ROWTYPE;
BEGIN
SELECT * INTO p_smtable FROM SUPERMARKET
WHERE invoice_id = invoiceID;
DBMS_OUTPUT.PUT_LINE(p_smtable.brancj || p_smtable.city);
END;
The compilation is successful.
Compile
begin
print_information('750-67-8428');
end;
But I get an error that says:
Error starting at line : 12 in command -
begin
print_information('750-67-8428');
end;
Error report -
ORA-06550: line 2, column 1:
PLS-00905: object SYSTEM.PRINT_INFORMATION is invalid
ORA-06550: line 2, column 1:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
The code in the screenshot is different to the version in your question, but both have an error at line 2. The parameter should be varchar2 or supermarket.invoice_id%type, with no semicolon.
Also, we normally use a p_ prefix for parameters, not variables. (There are other conventions, but whatever you use, p_ for a variable is just confusing.)
A fixed version might be:
create or replace procedure print_information
( p_invoice_id supermarket.invoice_id%type )
as
l_market supermarket%rowtype;
begin
select * into l_market
from supermarket
where invoice_id = p_invoice_id;
dbms_output.put_line(l_market.brancj || ' '|| l_market.city);
end;
Whatever tool you are using for development, you need to become familiar with how to display compilation errors.
brancj might be a typo for branch.
I've assumed you want a space between branch and city, otherwise the output would be something like TottenhamLondon rather than Tottenham London.
In Oracle a schema belongs to one user, created with the CREATE USER command. An Oracle Database is the entire thing (all users, all data, storage, memory, processes, everything) so you would not normally create one for something like this.

Oracle basic multi-statement block

In SQL Server, multiple statements in SSMS can be performed. In Oracle (using toad), I don't know why I receive certain errors doing the same thing. For example, I assume an Oracle requirement is to place them in a block, but I still get the following:
DECLARE
v_datetime TIMESTAMP := SYSDATE;
BEGIN
insert into sometable_log values (v_datetime, 'this is a test ',1);
select * from sometable_log where event_dt = v_datetime;
END;
produces:
[Error] Execution (5: 1): ORA-06550: line 4, column 1: PLS-00428: an
INTO clause is expected in this SELECT statement
Why would I need to use an into clause? Can someone please help me understand what this is?
Thank you!
When executing the block of code, Oracle expects that the select command should have some code-like effect. That's why it wants you to add the into clause.
To do what you need, just move the select statement outside of the PL/SQL begin/end block.

SYS_REFCURSOR out parameter - running stored procedure fails

I come from a SQL Server background but I'm struggling with this in Oracle. All of the sprocs in the database that's been configured expect a parameter passed in of type 'sys_refcursor'. In a nutshell, they do this (the sprocs are far more complex, but the whole cursor thing is what I'm getting at) :
CREATE OR REPLACE PROCEDURE xxx_API_TEST
(
TESTCURSOR OUT SYS_REFCURSOR
) AS
BEGIN
OPEN CURS FOR
SELECT * FROM SOMETABLE;
END xxx_API_TEST;
So - in Oracle SQL Developer I can run this no problem - and view the output of the cursor in the Output Variables window.
However, rather than have to keep reloading the dialog each time I want to retest it - I figured it'd be possible to copy the PL/SQL in the dialog to a new worksheet, and then just run that as I needed to - adjusting parameters to suit - so in this case, I'd run :
DECLARE
TESTCURSOR SYS_REFCURSOR;
BEGIN
xxx_API_TEST(
TESTCURSOR => TESTCURSOR
);
/* Legacy output:
DBMS_OUTPUT.PUT_LINE('TESTCURSOR = ' || TESTCURSOR );
*/
:TESTCURSOR := TESTCURSOR; --<-- Cursor
--rollback;
END;
Which is exactly the same as that shown in the Run dialog.
However, if I do this - it just throws an error - stating:
Error starting at line : 1 in command -
<snip>
Error report -
ORA-06550: line 11, column 20:
PLS-00382: expression is of wrong type
ORA-06550: line 11, column 3:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
I've no idea how to go about diagnosing this one. The fact it runs fine from the dialog but not the worksheet is puzzling - and inspecting what was sent to the DB I can't see any differences in the SQL it actually used.
Interestingly if I run this code from the worksheet - it pops up a dialog to ask for the value for TESTCURSOR - which the 'Run' dialog doesn't do. I just press OK - but I've tried both ticking and unticking the 'Null' checkbox to no avail.
Any help very much appreciated. It's Oracle 12c. If you need any more info just let me know.
Cheers,
Tony
Update: 20/7/2016
I ended up pulling the values into variables from a fetch, and just dumping to dbms_output - which gives me what I needed to repeatedly run the same sproc.
e.g.
loop
fetch testcursor into Res, ActDate<snip>;
exit when testcursor%notfound;
DBMS_OUTPUT.PUT_LINE(Res || ' | ' || ActDate etc etc);
end loop;
close testcursor;
The Run dialog is generated from the procedure spec and therefore knows the correct type for testcursor, but when you just paste it into a worksheet it doesn't, and it seems to define it as a text string. As of SQL Developer 4.0.3.16 the worksheet bind value prompt doesn't seem to have a way to change the datatype.
As for how to create a reusable test script with a cursor output in SQL Dev, I don't know. (I normally use PL/SQL Developer which can do this, but it's not free software.)
Edit: in this thread a solution was to write a wrapper function and select it from dual. I've just tried and you don't get a grid, but you get a kind of debug output without too much effort:
Oracle SQL Developer: Show REFCURSOR Results in Grid?

Stored Proc hitting ORA-06502: PL/SQL: numeric or value error

I'm having a problem calling a stored procedure from OSB 11g thru JCA Adapter.
The error I'm getting is:
ORA-06502: PL/SQL: numeric or value error
ORA-06512: at line 1
The error is as short as it is without any appends behind the error description. It only happens in production environment and there are no problems when I point the database to the UAT one.
More surprisingly, it will work in production envrionement if one of the variables I pass in is less than 128 characters. (or else I will hit the error above).
The stored procedure type and length are defined correctly. having the table column able to cope for 4000 characters.
Both Oracle 9i DB sharing the same major minor build revision. The stored proc is located in a package. I extracted out and compared the stored proc from both DB environments using winmerge and it shows they mirror each other.
Executing the stored procedure manually in production environment works, provides that I declare a big enough varchar size. I manage to simulate the ORA-06502 error by declaring a variable size lesser than the data length I'm passing in.
I even went as far as capturing the network dump from both executions and found there are slightly differences. (Note: I'm reusing the same datasource and only change the ip and username in WLS and did a restart before each executions)
When I point to production environment(the 1 having trouble), the tcpdump looks something like below:
BEGIN packagename.stored_proc_name(V_value1=>:1 , v_value2=>:2, v_value3=>:3); END .... {variable1}... {variable2}... {variable3})
When I point to UAT environment(the successful 1), the dump looks shorter and without the BEGIN; END tag
.... {variable1}... {variable2}... {variable3})
What else could have gone wrong? Appreciate for any helps!
"The stored proc is located in a package. I extracted out and compared the stored proc from both DB environments using winmerge and it shows
they mirror each other."
It is not about the code, the issue is data specific. In UAT you might not have production like data and thus you aren't able to replicate the issue.
Your error message just says error at line 1, which is not quite helpful. Are you executing the code without formatting it? If you format the code and execute it, and remove all exception handling, you will correctly know the line number. For example :
SQL> declare
2 num number;
3 begin
4 num := 'a';
5 end;
6 /
declare
*
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 4
See, it clearly tells that error is at line 4.
By any chance if you have an EXCEPTION block, then make sure you use dbms_utility.format_error_stack and dbms_utility.format_error_backtrace to log the error details. Else, the error line number will be never correct.

Resources