I posted the following puzzle on Twitter:
White space
so you do not immediately
see my answer.
:-)
Here are the answers from the TwitterSphere:
Change line 5's assignment to dbms_sql.number_table(1=>1,2=>1)
In other words, try to insert the same value twice. Since there is a unique index on the column, that will cause ORA-00001 to be raised.
So that will do it, right?
Wrong. Hans and Dirk both point out why that is not enough, and offer the second part of the solution:
The value deposited in the error_code field of the SQL%BULK_EXCEPTIONS array is unsigned. In other words, 1 rather than -1 is stored. Unfortunately, the SQLERRM function assumes that the error code you pass it will be signed (negatively). So you must multiply the value in the pseudo-collection by -1. Then SQLERRM will return the right string.
Or as Dirk puts it:
(sqlerrm (sql%bulk_exceptions (indx).error_code));
must be
(sqlerrm (0 - sql%bulk_exceptions (indx).error_code));
You don't really need the 0, though. You can write simply:
(sqlerrm (-sql%bulk_exceptions (indx).error_code));
You can see all these variations at work in my LiveSQL script.
Actually, I was surprised that I did not receive any "silly" answers. After all, there are lots of ways to get "ORA-00001: unique constraint" to appear on the screen, such as:
Yes, that's right, simply display it on the screen and then shortcut everything else with RETURN; (or not, let the rest of the code execute unchanged).
I guess it was a serious week for the Oracle Database developer community. :-)
What change(s) can you make to this code so that "ORA-00001: unique constraint" appears on the screen after execution?Try it yourself before reading the rest of the post!
White space
so you do not immediately
see my answer.
:-)
Change line 5's assignment to dbms_sql.number_table(1=>1,2=>1)
In other words, try to insert the same value twice. Since there is a unique index on the column, that will cause ORA-00001 to be raised.
So that will do it, right?
Wrong. Hans and Dirk both point out why that is not enough, and offer the second part of the solution:
The value deposited in the error_code field of the SQL%BULK_EXCEPTIONS array is unsigned. In other words, 1 rather than -1 is stored. Unfortunately, the SQLERRM function assumes that the error code you pass it will be signed (negatively). So you must multiply the value in the pseudo-collection by -1. Then SQLERRM will return the right string.
Or as Dirk puts it:
(sqlerrm (sql%bulk_exceptions (indx).error_code));
must be
(sqlerrm (0 - sql%bulk_exceptions (indx).error_code));
You don't really need the 0, though. You can write simply:
(sqlerrm (-sql%bulk_exceptions (indx).error_code));
You can see all these variations at work in my LiveSQL script.
Actually, I was surprised that I did not receive any "silly" answers. After all, there are lots of ways to get "ORA-00001: unique constraint" to appear on the screen, such as:
DECLARE
two_ts DBMS_SQL.number_table := DBMS_SQL.number_table (1=>1,2=>2);
BEGIN
DBMS_OUTPUT.PUT_LINE ('ORA-00001: unique constraint');
RETURN;
FORALL indx IN 1 .. 2
SAVE EXCEPTIONS
INSERT INTO t VALUES (two_ts(indx));
DBMS_OUTPUT.put_line (SQL%ROWCOUNT || ' inserted');
ROLLBACK;
EXCEPTION
WHEN others
THEN
FOR indx IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
LOOP
DBMS_OUTPUT.put_line
(SQLERRM (SQL%BULK_EXCEPTIONS (indx).ERROR_CODE));
END LOOP;
END;
Yes, that's right, simply display it on the screen and then shortcut everything else with RETURN; (or not, let the rest of the code execute unchanged).
I guess it was a serious week for the Oracle Database developer community. :-)
Comments
Post a Comment