8

How can I get position of an error in the query?

I need to get position in a query string which causes an error, like sqlplus does it:

SQL> insert into tbl (data) values('12345')
  2  /
insert into tbl (data) values('12345')
                 *
ERROR at line 1:
ORA-12899: value too large for column "schmnm"."tbl"."data" (actual: 5,
maximum: 3)

How can I do that?

4
  • I highly doubt you can. I'd try the debugger (or wireshark and look at the data on the wire) and see if anything else but the error text is returned from the server. If I had to guess that logic is in the oracle sqlplus client itself. Even if that isn't the case ... it's probably discarded below what's exposed via JDBC Commented Jul 8, 2013 at 16:56
  • There are two levels to determine the error in a query: syntax and data. Are you restricted to the data or do you need to check syntax too? Commented Jul 8, 2013 at 17:06
  • @Gamb, syntax is not much important, I check query before using it, however it may have runtime exceptions and I need to catch them and make a user friendly message. Commented Jul 8, 2013 at 17:08
  • @BrianRoach it is OCI client lib feature. In OCI an ErrorHandle is a vector of strings. So if sqlplus returns several lines of error message, each line is one field of this vector. For some unknown reason JDBC SQLException's error message contains only the 1st field of the vector. I think that the rest is silently discarded, there is no access to it. these error messages are really annoying when Oracle tells you that some constrain was violated, but will not tell you which one. The name of the constraint is usually in the 2nd field of the vector. Commented Oct 2, 2015 at 12:05

3 Answers 3

5
+100

After some ramblings when I almost lost hope, I found (thanks to correct search string in Google) following link: https://forums.oracle.com/thread/1000551

SQL> DECLARE
  2     c   INTEGER := DBMS_SQL.open_cursor ();
  3  BEGIN
  4     DBMS_SQL.parse (c, 'select * form dual', DBMS_SQL.native);
  5
  6     DBMS_SQL.close_cursor (c);
  7  EXCEPTION
  8     WHEN OTHERS THEN
  9        DBMS_OUTPUT.put_line ('Last Error: ' || DBMS_SQL.LAST_ERROR_POSITION ());
 10        DBMS_SQL.close_cursor (c);
 11        RAISE;
 12  END;
 13  /
Last Error: 9
DECLARE
*
ERROR at line 1:
ORA-00923: FROM keyword not found where expected
ORA-06512: at line 11
Sign up to request clarification or add additional context in comments.

Comments

3

To expand on accepted answer I'll provide JDBC code necessary to retrieve error position from SQL query.

PL/SQL:

This PL/SQL block accepts sql query text and returns error position:

DECLARE
  c        INTEGER := DBMS_SQL.open_cursor();
  errorpos integer := -1;
BEGIN
  BEGIN
    DBMS_SQL.parse(c, :sqltext, DBMS_SQL.native);
  EXCEPTION
    WHEN OTHERS THEN
      errorpos := DBMS_SQL.LAST_ERROR_POSITION();
  END;
  :errorpos := errorpos;
  DBMS_SQL.close_cursor(c);
END;

It accepts two parameters sqltext and errorpos.

Java:

On Java side we need to call PL/SQL code from above and retrieve error position. Here's a method for that:

private int retrieveErrorPosition(Connection connection, String query) {
    CallableStatement callStatement = null;
    try {
        callStatement = connection.prepareCall(LAST_ERROR_POSITION_QUERY);
        callStatement.setString(1, query);
        callStatement.registerOutParameter(2, OracleTypes.INTEGER);
        callStatement.execute();
        return callStatement.getInt(2);
    } catch (SQLException ex) {
        log.log(Level.SEVERE, "", ex);
    } finally {
        if (callStatement != null) {
            try {
                callStatement.close();
            } catch (SQLException sqle) {
            }
        }
    }
    return -1;
}

Usage:

Now, if query string executes with exception we can extract error position:

String query;
Connection connection;
try {
    //normal query execution
} catch (SQLException ex) {
    int sqlErrorPosition = retrieveErrorPosition(connection, query);
    //exception handling
}

Comments

1

The SQLException has additional fields that hold the SQL error number (as in ORA-12899) and a message something like what you see as value too large for column "schmnm"."tbl"."data" (actual: 5, maximum: 3)

You have to parse the string if you want to truely pinpoint the error in the SQL statement.

See: http://docs.oracle.com/javase/6/docs/api/java/sql/SQLException.html

Read about the errorCode and SQLState properties within the exception.

1 Comment

That is so true, but it doesn't bother me so much when its generated by a stable sort of system like an Oracle database. When the Oracle version changes, you would have to watch for changes just to be vigilant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.