如何将no_data_found异常重写为用户自定义异常?

How to rewrite no_data_found exception into a user-defined exception?

这是捕获 Oracle 异常的代码

set serveroutput on;
ACCEPT identifiant PROMPT 'id';
DECLARE
    vType PARCELLE.TypeP%Type;
    vSuperf PARCELLE.Superf%Type;
BEGIN
    SELECT distinct TypeP,Superf INTO vType,vSuperf
    FROM PARCELLE
    WHERE PARCELLE.NumPropC='&identifiant' 
    AND Superf=(select MAX(Superf) from PARCELLE
      where PARCELLE.NumPropC='&identifiant');
    DBMS_OUTPUT.PUT_LINE('id:'||'&identifiant'||',type:'||vType
      ||',Supeficie:'||vSuperf);
EXCEPTION
    WHEN no_data_found THEN
        dbms_output.put_line('Aucun Propriétaire vous cherchez.');  
END;

我现在需要做的是编写另一个版本,不使用内置异常,而是使用用户定义的异常。结果应该是一样的。

我试过这样的东西

BEGIN
    SELECT distinct TypeP,Superf INTO vType,vSuperf
    FROM PARCELLE
    WHERE PARCELLE.NumPropC='&identifiant' 
    AND Superf=(select MAX(Superf) from PARCELLE 
      where PARCELLE.NumPropC='&identifiant');
    IF vType IS NULL OR vSuperf IS NULL THEN RAISE non_trouve;
    END IF;
    DBMS_OUTPUT.PUT_LINE('id:'||'&identifiant'||',type:'||vType
      ||',Supeficie:'||vSuperf);
EXCEPTION
    WHEN non_trouve THEN
        dbms_output.put_line('Aucun Propriétaire vous cherchez.');

在达到跳转到异常的条件之前,它首先returns内置异常(未找到)。

我尝试了另一种方式:

DECLARE
    vType PARCELLE.TypeP%Type;
    vSuperf PARCELLE.Superf%Type;
    non_trouve EXCEPTION;
    vToutProp PROPRIETAIRE.NumPropC%TYPE;
BEGIN
    SELECT * INTO vToutProp FROM PROPRIETAIRE;
    IF '&identifiant' NOT IN (vToutProp) THEN RAISE non_trouve;
    END IF;
--same left

但这是完全错误的,因为我应该声明一个数组或其他东西,但我不知道如何处理它。

有人有想法吗?

也许这会有所帮助。在 Oracle PL SQL 中,您可以创建自己的异常,如下所示

  PROCEDURE ProcedureName

  IS
     CUSTOM_EXCEPTION  EXCEPTION;

  BEGIN

     -- code here
     RAISE CUSTOM_EXCEPTION

  EXCEPTION
     WHEN CUSTOM_EXCEPTION THEN
        -- code for CUSTOM_EXCEPTION

  END ProcedureName

由于不允许使用内置异常,请使用计数函数检查数据是否存在。如果不是,则引发自定义异常。

set serveroutput ON;
ACCEPT identifiant prompt 'id';
DECLARE
    v_count NUMBER := 0;
    e_non_trouve EXCEPTION;
BEGIN
    SELECT Count(1)
    INTO   v_count
    FROM   parcelle
    WHERE  parcelle.numpropc = '&identifiant'
           AND superf = (SELECT Max(superf)
                         FROM   parcelle
                         WHERE  parcelle.numpropc = '&identifiant');


    IF v_count = 0 THEN
      RAISE e_non_trouve;
    END IF;
EXCEPTION
    WHEN e_non_trouve THEN
      dbms_output.Put_line('Aucun Propriétaire vous cherchez.');
END; 

嗯,老实说,如果您要做的只是像在示例代码中那样吸收异常,那么您不会 "need to do now" 做任何此类事情。在我的脑海中,我只能想到使用用户定义异常的两个原因:

  1. 您想在过程外传播异常,并且希望它对调用者有意义。所以你想把 "no data found" 变成 "that student is not currently enrolled in that class."
  2. 过程中有几个位置可能引发 "no data found" 异常,但重要性(以及含义)因引发的位置而异。您希望外层异常处理程序能够辨别差异。

如果是第二个选项,做这样的事情可能同样好或更好:

err_code := 1;
-- perform something that might raise no_data_found
...
err_code := 2;
-- perform something else that might raise no_data_found
...
err_code := 3;
-- perform something else that might raise no_data_found
...
exception
    when no_data_found then
        if err_code = 1 then
            Raise_application_error( -20001, 'Student not enrolled in that class';
        elsif err_code = 2 then
            Raise_application_error( -20001, 'Student not making a passing grade in class';
        elsif err_code = 3 then
            Raise_application_error( -20001, 'Only you can prevent forest fires!';
        end if;
    when others then
        -- uh-oh
end proc;

它并不花哨,但它完成了工作。