Dựa trên câu hỏi, tôi không đồng ý với câu trả lời được chấp nhận. Câu hỏi hiển thị một kịch bản lệnh nhiều câu lệnh. RAISE_APPLICATION_ERROR() chỉ thoát ra khỏi một khối PL/SQL (chương trình con), không nằm ngoài tập lệnh tổng thể (như được chỉ ra bởi Justin) vì vậy nó sẽ tiếp tục với các câu lệnh tiếp theo.
Đối với tập lệnh theo lô, tốt nhất bạn nên sử dụng WHENEVER SQLERROR EXIT. Vâng, đó là một chỉ thị SQL * Plus, không phải là SQL chuẩn, nhưng khá là di động; các công cụ Oracle phổ biến nhất hỗ trợ các tập lệnh hỗ trợ chỉ thị này, ít nhất một phần. Ví dụ sau đây hoạt động trong SQL * Plus, SQL * Developer, Toad, SQLsmith và có thể là những người khác, và thể hiện vấn đề, nếu bạn bình luận dòng đó.
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;
/
Nếu bạn loại bỏ WHEN SQLERROR, tập lệnh sẽ tiếp tục và thực thi khối thứ 2, v.v ... chính xác là câu hỏi cần tránh. Lợi ích, trong trường hợp này, các công cụ đồ họa mô phỏng sqlplus, là chúng thực sự dừng kịch bản và không gửi phần còn lại của kịch bản lệnh shell như lệnh shell, đó là những gì sẽ xảy ra nếu bạn dán tập lệnh vào SQL * Plus đang chạy trong cửa sổ bảng điều khiển. SQL * Plus có thể thoát do lỗi, nhưng các lệnh đệm còn lại sau đó sẽ được xử lý bởi vỏ hệ điều hành, một chút lộn xộn và có khả năng nguy hiểm, nếu bạn có lệnh shell trong các chú thích (không phải là chưa từng nghe). Với SQLPlus, nó luôn luôn là tốt nhất để kết nối, và sau đó thực thi kịch bản, hoặc vượt qua nó trong đối số dòng lệnh < start (sqlplus scott/tiger @ foo.sql) để tránh điều này.
Bạn có thực sự đang nói về một tập lệnh PL/SQL không? Hoặc một kịch bản lệnh SQL * Plus? Bạn không thể có một câu lệnh DDL trong PL/SQL (trừ khi bạn đặt nó trong một 'EXECUTE IMMEDIATE'). Vì vậy, nó xuất hiện với tôi rằng bạn đang nói về một kịch bản SQL * Plus. Nếu bạn đang nói về một kịch bản lệnh SQL * Plus, nếu khối PL/SQL bị lỗi, SQL * Plus sẽ mặc định tiếp tục thực hiện câu lệnh SQL tiếp theo (hoặc khối PL/SQL) trong kịch bản lệnh. Bạn sẽ cần sử dụng lệnh SQL * Plus 'WHENEVER SQLERROR EXIT'. –
Cảm ơn bạn đã bình luận của bạn Justin. Trong thực tế, tôi không phải là một "chuyên gia Oracle", ngay cả khi tôi có kiến thức tốt về DBMS nói chung. Vì vậy, tôi chưa nắm được sự khác biệt giữa các kịch bản lệnh PL/SQL hoặc SQL * Plus (bạn có biết một số blog/doc/trang web giải thích rõ ràng sự khác biệt đó không?). Tất cả những gì tôi có thể nói là tôi đang sử dụng ** Navicat **, sử dụng cửa sổ "truy vấn" và tải tệp kịch bản của tôi vào đó. Trong bối cảnh cụ thể đó, 'RAISE_APPLICATION_ERROR()' thực hiện công việc. –