Basado en la pregunta, no estoy de acuerdo con la respuesta aceptada. La pregunta muestra un script por lotes de varias declaraciones. RAISE_APPLICATION_ERROR() solo sale de un bloque PL/SQL (subprograma), no fuera del guión general (como lo señala Justin), por lo que continuará con las afirmaciones que siguen.
Para las secuencias de comandos por lotes, es mejor utilizar WHENEVER SQLERROR EXIT. Sí, es una directiva SQL * Plus, no SQL estándar, pero es bastante portátil; las herramientas de Oracle más populares que admiten scripts admiten esta directiva, al menos parcialmente. El siguiente ejemplo funciona en SQL * Plus, SQL * Developer, Toad, SQLsmith y posiblemente otros, y demuestra el problema, si comenta la línea.
set serveroutput on
-- Without this line, things keep going
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK;
BEGIN
IF (1 > 0) THEN
DBMS_OUTPUT.PUT_LINE('First thing');
RAISE_APPLICATION_ERROR(-20000, 'Test failed'); -- not enough
END IF;
END;
/
-- This will execute if you remove WHEN SQLERROR.., so RAISE_APPLICATION_ERROR is not enough
BEGIN
DBMS_OUTPUT.PUT_LINE('Second thing - Executes anyway');
END;
/
Si extrae la CUANDO SQLERROR, el guión va a continuar y ejecutar el segundo bloque, etc., que es exactamente lo que la pregunta se refiere a evitar.
La ventaja, en este caso, de las herramientas gráficas que emulan sqlplus, es que realmente detienen el script y no envían el resto del script al shell del comando como comandos de shell, que es lo que sucede si pega scripts en SQL * Plus que se ejecutan en una ventana de consola. SQL * Plus puede salir en caso de error, pero los comandos almacenados restantes serán manejados por el shell del sistema operativo, que es un poco desordenado y potencialmente riesgoso, si tiene comandos de shell en los comentarios (que no es desconocido). Con SQLPlus, siempre es mejor conectarse, y luego ejecutar el script, o pasarlo en el argumento < start> command line (sqlplus scott/tiger @ foo.sql) para evitar esto.
¿Estás hablando realmente de un script PL/SQL? ¿O una secuencia de comandos SQL * Plus? No se puede tener una instrucción DDL en PL/SQL (a menos que la coloque en un 'EJECUTAR INMEDIATO'). Entonces me parece que estás hablando de un script SQL * Plus. Si está hablando de un script SQL * Plus, si el bloque PL/SQL se equivoca, SQL * Plus continuará ejecutando de forma predeterminada la siguiente instrucción SQL (o bloque PL/SQL) en el script. Debería usar el comando SQL * Plus 'WHENEVER SQLERROR EXIT'. –
Gracias por tu comentario Justin. De hecho, no soy un "experto en Oracle", incluso si tengo un buen conocimiento de DBMS en general. Por lo tanto, todavía no entendía la diferencia entre los scripts PL/SQL o SQL * Plus (¿conoces algún blog/doc/sitio que explique claramente esa diferencia?). Todo lo que puedo decir es que estoy usando ** Navicat **, usando el panel de "consulta" y cargando el archivo de mi script en él. En ese contexto específico, 'RAISE_APPLICATION_ERROR()' hace el trabajo. –