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

时间:2015-02-09 18:11:11

标签: oracle plsql

以下是捕获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.');

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

我尝试了另一种方式:

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

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

任何人都有想法?

3 个答案:

答案 0 :(得分:0)

也许这会有所帮助。在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

答案 1 :(得分:0)

由于您不允许使用内置异常,请使用count函数检查数据是否存在。如果没有,请提出自定义异常。

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; 

答案 2 :(得分:0)

嗯,说实话,你现在不需要做"如果您要做的就是像示例代码中那样吸收异常。在我的头脑中,我只能想到使用用户定义的例外的两个原因:

  1. 您希望在过程外传播异常,并希望它对调用者有意义。所以你想转向"没有找到数据"进入"该学生目前没有注册该课程。"
  2. 程序中有多个位置可能会引发"没有找到数据"异常,但意义(因而意义)取决于它的提升位置。您希望外层异常处理程序能够识别差异。
  3. 如果是第二种选择,那么做这样的事情可能会更好或更好:

    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;
    

    它并不华丽,但它完成了工作。