-2

SQL> DESC 宿舍;

Name                                      Null?             Type 
    ------------------------------------  --------          ------------------- 
    HOSTELID                              NOT NULL          VARCHAR2(4) 
    ROOMSAVAILABLE                                              NUMBER(3) 
    HOSTELTYPE                                              VARCHAR2(1) 
    HOSTELFEE                                               NUMBER(6) 

SQL> SELECT * FROM 宿舍;

HOST    ROOMSAVAILABLE      H       HOSTELFEE 
------- ---------------------- ----     --------------------- 
H1              2           M           2000 
H2              3           F           3000

上面显示了一个表格宿舍和其中的值。以下 pl/sql 程序的输出是什么?请详细解释。

CREATE OR REPLACE PROCEDURE sp_validatehostelid 
(p_hostelid IN hostel.hostelid%TYPE, 
p_hostelfee OUT hostel.hostelfee%TYPE 
) 
IS 
v_count NUMBER; 
v_hostelfee hostel.hostelfee%TYPE; 
BEGIN 
SELECT COUNT(*) INTO v_count FROM hostel WHERE hostelid=p_hostelid; 
IF v_count=0 THEN 
RAISE_APPLICATION_ERROR(-20000,'Invalid Hostel id'); 
ELSE 
SELECT hostelfee INTO v_hostelfee FROM hostel WHERE hostelid=p_hostelid; 
DBMS_OUTPUT.PUT_LINE('Hostel Fee:'||v_hostelfee); 
END IF; 
EXCEPTION 
WHEN NO_DATA_FOUND THEN 
DBMS_OUTPUT.PUT_LINE('No data found'); 
WHEN OTHERS THEN 
DBMS_OUTPUT.PUT_LINE('Other Errors in Procedure'); 
END sp_validatehostelid; 
Procedure created. 

DECLARE 
g_hostelfee hostel.hostelfee%TYPE; 
BEGIN 
sp_validatehostelid('H5',g_hostelfee); 
EXCEPTION 
WHEN OTHERS THEN 
DBMS_OUTPUT.PUT_LINE('Other Errors in Block'); 
END;
4

2 回答 2

2

“输出会是什么?假设没有 hostelid = 'H5' 的行”

假设您在启用了服务器输出的客户端中运行它,输出将是

Other Errors in Procedure
PL/SQL procedure successfully completed.

SQL>

为什么?

  1. 第一个选择语句是一个计数,它不能抛出 NO_DATA_FOUND 异常。
  2. 下一行引发用户定义的异常 -20000。
  3. 这会将控制权传递给异常处理程序块。-20000 不是 NO_DATA_FOUND 所以执行了 WHEN OTHERS 子句,它显示了上面的消息。
  4. 异常处理程序本身不会引发异常,这是非常糟糕的做法。所以流程返回到调用块。
  5. 因为没有发现异常,调用块认为被调用的过程执行成功,所以处理干净地终止。这就是为什么不重新引发异常是不好的做法。

请注意,如果您在没有先启用 serveroutput 的情况下运行它,则输出将是:

PL/SQL procedure successfully completed.

SQL>
于 2013-07-04T14:04:42.620 回答
-1
CREATE OR REPLACE PROCEDURE sp_validatehostelid 
(
    p_hostelid IN hostel.hostelid%TYPE, 
    p_hostelfee OUT hostel.hostelfee%TYPE 
) 
IS 
    v_count NUMBER; 
    v_hostelfee hostel.hostelfee%TYPE; 
BEGIN 
    /* Count rows in 'hostel' table for given ID */
    SELECT COUNT(*) INTO v_count FROM hostel WHERE hostelid=p_hostelid; 
    /* If there is noting in the table */
    IF v_count=0 THEN 
        /* raise exception */
        RAISE_APPLICATION_ERROR(-20000,'Invalid Hostel id'); 
    ELSE
        /* select fee from the 'hostel' table */
        SELECT hostelfee INTO v_hostelfee FROM hostel WHERE hostelid=p_hostelid; 
        /* print the fee */
        DBMS_OUTPUT.PUT_LINE('Hostel Fee:'||v_hostelfee); 
    END IF; 
EXCEPTION 
    WHEN NO_DATA_FOUND THEN 
        DBMS_OUTPUT.PUT_LINE('No data found'); 
    WHEN OTHERS THEN 
        DBMS_OUTPUT.PUT_LINE('Other Errors in Procedure'); 
END sp_validatehostelid; 


DECLARE 
    g_hostelfee hostel.hostelfee%TYPE; 
BEGIN 
    sp_validatehostelid('H5',g_hostelfee); 

    /* 
    **Here something should be done with 'g_hostelfee' variable
    */
EXCEPTION 
    WHEN OTHERS THEN 
        DBMS_OUTPUT.PUT_LINE('Other Errors in Block'); 
END;

如果有一行 hostelid = 'H5' 收取给定 ID 的费用,打印并传递出去。

注意:它仅适用于每个 ID 的一行。如果有不止一个。将引发 TO_MANY_VALUES 异常。

于 2013-07-04T08:21:21.633 回答