Na podstawie tego pytania nie zgadzam się z zaakceptowaną odpowiedzią. Pytanie pokazuje skrypt wsadowy z wieloma instrukcjami. Funkcja RAISE_APPLICATION_ERROR() wychodzi tylko z bloku PL/SQL (podprogramu), a nie z całego skryptu (jak zauważył Justin), więc będzie kontynuowana z następującymi instrukcjami.
W przypadku skryptów wsadowych najlepiej jest użyć WHENEVER SQLERROR EXIT. Tak, jest to dyrektywa SQL * Plus, a nie standardowy SQL, ale jest dość przenośna; najpopularniejsze narzędzia Oracle obsługujące skrypty obsługują tę dyrektywę, przynajmniej częściowo. Poniższy przykład działa w SQL * Plus, SQL * Developer, Toad, SQLsmith i prawdopodobnie innych, i demonstruje problem, jeśli skomentujesz linię.
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;
/
Jeśli usunąć KIEDY SQLERROR, skrypt będzie kontynuować i wykonać 2nd blok, itp, które to właśnie pytanie zadaje się uniknąć.
Zaletą w tym przypadku narzędzi graficznych emulujących sqlplus jest to, że naprawdę zatrzymują skrypt i nie przekazują pozostałej części skryptu do powłoki poleceń jako polecenia powłoki, co dzieje się po wklejeniu skrypty do SQL * Plus uruchomione w oknie konsoli. SQL * Plus może wyjść z błędem, ale pozostałe buforowane polecenia będą obsługiwane przez powłokę systemu operacyjnego, która jest nieco chaotyczna i potencjalnie ryzykowna, jeśli w komentarzach byłyby polecenia powłoki (co nie jest niespotykane). Z SQLPlus zawsze najlepiej jest połączyć się, a następnie wykonać skrypt lub przekazać go w argumencie linii poleceń < start (sqlplus scott/tiger @ foo.sql), aby tego uniknąć.
Czy naprawdę mówisz o skrypcie PL/SQL? Lub skrypt SQL * Plus? Nie możesz mieć instrukcji DDL w PL/SQL (chyba że umieścisz ją w "WYKONAJ NATYCHMIAST"). Wydaje mi się, że mówisz o skrypcie SQL * Plus. Jeśli mówimy o skrypcie SQL * Plus, jeśli błędy bloku PL/SQL się nie powiedzie, SQL * Plus domyślnie będzie kontynuował wykonywanie w skrypcie następnej instrukcji SQL (lub bloku PL/SQL). Będziesz musiał użyć polecenia SQL * Plus 'WHENEVER SQLERROR EXIT'. –
Dzięki za komentarz Justin. W rzeczywistości nie jestem "ekspertem Oracle", nawet jeśli mam dobrą znajomość DBMS w ogóle. W związku z tym nie zrozumiałem jeszcze różnicy pomiędzy skryptami PL/SQL lub SQL * Plus (znasz bloga/doc/stronę wyjaśniającą wyraźnie różnicę?). Wszystko, co mogę powiedzieć, to to, że używam ** Navicat **, używając okienka "zapytanie" i ładuję do niego mój plik skryptu. W tym konkretnym kontekście '' RAISE_APPLICATION_ERROR() 'wykonuje zadanie. –