发现数据时PL SQL引发异常

Jon*_*nny 4 plsql exception package oracle11g

我一直在研究预定义的Oracle pl/SQL异常.我想在找到数据时引发异常.我已经能够看到NO_DATA_FOUND异常了.但不是相反.什么是最好的方法,或者不建议执行这种操作.

我的程序如下

PROCEDURE CHECK_ASSIGNED AS

PLACEHOLDER INT;   

BEGIN

SELECT v.id
INTO PLACEHOLDER
FROM vinegar v
WHERE NOT EXISTS (
SELECT 1
FROM home h
WHERE h.sid = v.sid
)

END;
-- when data is found it means that and sid does not exist in the home table
-- should raise exception and stop package
Run Code Online (Sandbox Code Playgroud)

All*_*lan 7

"找到的数据"没有内置错误,因为Oracle不会将查找数据视为错误.但是,在特定情况下将此案例视为错误并不太难.

这在某种程度上取决于你想对异常做什么.如果你想在程序中以某种方式对它做出反应,你可以定义自己的异常,然后提高它:

PROCEDURE check_assigned AS
   exception err_data_found;
   placeholder INT;
BEGIN
   SELECT v.id
   INTO   placeholder
   FROM   vinegar v
   WHERE  NOT EXISTS
             (SELECT 1
              FROM   home h
              WHERE  h.sid = v.sid);

   IF SQL%FOUND THEN
      RAISE err_data_found;
   END IF;
EXCEPTION
   WHEN err_data_found THEN
      NULL;
      --do something
END;
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您只想将错误返回给调用者,则可以使用raise_application_error:

PROCEDURE check_assigned AS
   placeholder INT;
BEGIN
   SELECT v.id
   INTO   placeholder
   FROM   vinegar v
   WHERE  NOT EXISTS
             (SELECT 1
              FROM   home h
              WHERE  h.sid = v.sid);

   IF SQL%FOUND THEN
      raise_application_error (-20001,
                               'Data was found in the vinegar table.');
   END IF;
END;
Run Code Online (Sandbox Code Playgroud)

如果目标是在任何行存在时引发错误并继续,则以这种方式执行它有点危险,因为您冒险触发NO_DATA_FOUND或者TOO_MANY_ROWS.您可以通过选择注释中建议的计数来解决这个问题,但我更喜欢使用显式游标来避免这些问题.

PROCEDURE check_assigned AS
   placeholder INT;

   CURSOR cur_vinegar_check IS
      SELECT v.id
      INTO   placeholder
      FROM   vinegar v
      WHERE      NOT EXISTS
                    (SELECT 1
                     FROM   home h
                     WHERE  h.sid = v.sid)
             AND ROWNUM = 1;
BEGIN
   OPEN cur_vinegar_check;
   FETCH cur_vinegar_check INTO placeholder;

   IF SQL%FOUND THEN
      raise_application_error (-20001,
                               'Data was found in the vinegar table.');
   END IF;

   CLOSE cur_vinegar_check;
END check_assigned;
Run Code Online (Sandbox Code Playgroud)

您会注意到我添加AND ROWNUM = 1到查询中.这是rownum外部查询中可预测的少数几次之一:您关心的是一行是否存在; 你不在乎它是哪一排.如果有可能返回大量行,则可以获得显着的性能优势.