PL SQL 找到数据时引发异常

PL SQL Raise Exception when data found

我一直在查看预定义的 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

"data found" 没有内置错误,因为 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;

另一方面,如果您只想return将错误告知调用者,您可以使用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;

如果目标是在存在任何行时引发错误并继续,否则这样做会有些危险,因为您有触发 NO_DATA_FOUNDTOO_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;

您会注意到我在查询中添加了 AND ROWNUM = 1。这是 rownum 在外部查询中可预测的少数情况之一:您所关心的只是一行是否存在;你不在乎它在哪一行。如果您有可能得到很多行 returned,这会带来显着的性能优势。

您可以引发用户定义的异常。

PROCEDURE CHECK_ASSIGNED AS

PLACEHOLDER INT;   
custom_exception  EXCEPTION;

BEGIN

SELECT v.id
INTO PLACEHOLDER
FROM vinegar v
WHERE NOT EXISTS (
SELECT 1
FROM home h
WHERE h.sid = v.sid
)
if PLACEHOLDER is not null 
then
   raise custom_exception;
end if;

exception
when custom_exception 
then 
   --do whatever exception stuff you want here
   DBMS_OUTPUT.PUT_LINE(SQLERRM);

END;