2017-12-08 3 views
0

1つのIDが間違っている5人の従業員の従業員の経験を印刷するタイプを作成しました。私はそれをスキップするために例外を作成しましたが、私はそれの結果を取得していません。私は何の間違いをしたのですか?私の質問を参照して、エラーを伝えてください。事前にタイプの作成と実行

CREATE OR REPLACE TYPE emp_id_typ IS TABLE OF NUMBER; 
/

CREATE OR REPLACE TYPE emp_exp_typ IS TABLE OF NUMBER; 
/

CREATE OR REPLACE PROCEDURE exp_sp (p_empid IN emp_id_typ 
            , p_exp  OUT emp_exp_typ) 
IS 
v_exp NUMBER; 
BEGIN 
    FOR i IN p_empid.FIRST..p_empid.COUNT 
    LOOP 
    p_exp.EXTEND; 
    SELECT ROUND(MONTHS_BETWEEN(SYSDATE, hire_date)/12) INTO v_exp FROM employees 
    WHERE employee_id = p_empid(i); 
    p_exp(p_exp.LAST) := v_exp; 
    END LOOP; 
    EXCEPTION 
    WHEN OTHERS THEN 
     v_exp := NVL(v_exp, 'NULL'); 
END exp_sp; 
/

DECLARE 
    v_empid emp_id_typ := emp_id_typ(); 
    v_exp emp_exp_typ := emp_exp_typ(); 
BEGIN 
    v_empid := emp_id_typ(101, 102, 52, 100, 206); 
    FOR i IN v_empid.FIRST..v_empid.COUNT 
    LOOP 
    exp_sp(v_empid(i), v_exp(i)); 
    dbms_output.put_line(v_empid(i), v_exp(i)); 
    END LOOP; 
END; 
/

おかげで...

+0

あなたが見ているものはよくわかりません。あなたのクライアントは 'dbms_output'バッファを見るように設定されていますか?例えばSQL \ * PlusまたはSQL Developerで 'set serveroutput on'を実行するか、IDEで接続するために有効にしますか?あるいは '他のとき'ハンドラが 'v_exp'の代わりに' p_exp'に値を代入することになっていますか?文字列 '' NULL ''を 'number'コレクションに代入することはできません... –

+0

いいえ私は練習していません –

+0

"結果が得られません"というのは、それが実行されることを意味しますが、実際には匿名ブロックからエラーを得るのに対し、期待した結果は得られません。あなたが期待していることと実際にあなたの質問に表示されているものを含めると、本当にはるかに役立ちます。 –

答えて

2

は、プロシージャと無名ブロックの両方でいくつかのエラーを持っています。手順内:

  • OUT p_expコレクションを初期化していません。それはOUTパラメータであるため、プロシージャ内で実行する必要があります。 (またはIN OUTにします)。
  • 例外ハンドラがループを終了するため、そこに設定したv_expは使用されず、p_expコレクションは不完全です。 (when othersを使用することも悪いことです)
  • 数値変数またはコレクションに `` NULL ''のような文字列を割り当てることはできません。呼び出し元にエラーを表すマジック番号を割り当てるか、nullのままにします。
    CREATE OR REPLACE PROCEDURE exp_sp (p_empid IN emp_id_typ 
                , p_exp  OUT emp_exp_typ) 
    IS 
        v_exp NUMBER; 
    BEGIN 
        -- have to initialise p_exp 
        p_exp := emp_exp_typ(); 
        -- better to use either 1..count, or first..last; don't mix them 
        --FOR i IN p_empid.FIRST..p_empid.COUNT 
        FOR i IN p_empid.FIRST..p_empid.LAST 
        LOOP 
        p_exp.EXTEND; 
        -- you want the exception handler to deal with this row then continue, 
        -- so use a nested block 
        BEGIN 
         SELECT ROUND(MONTHS_BETWEEN(SYSDATE, hire_date)/12) INTO v_exp FROM employees 
         WHERE employee_id = p_empid(i); 
        EXCEPTION 
         WHEN OTHERS THEN 
         -- you can't assign a string to a number 
         --v_exp := NVL(v_exp, 'NULL'); 
         -- just an example as not clear what you need 
         v_exp := -1; 
        END; -- nested block with exception handler 
        p_exp(p_exp.LAST) := v_exp; 
        END LOOP; 
    END exp_sp; 
    /
    

    そして、あなたの無名ブロック内

  • v_expの初期化は、手続きの引数はOUTであるとして冗長です。エラーではなく無意味です。
  • ループ内のプロシージャを呼び出して、単一の要素を渡しています。ループの外側で一度呼び出され、コレクション全体を渡す必要があります。
  • dbms_output.put_lineへのお電話は間違っています。 1つの引数しか取らないので、たとえば文字列を構築する必要があります。連結して取得
DECLARE 
    v_empid emp_id_typ := emp_id_typ(); 
    -- assignment is redundant 
    -- v_exp emp_exp_typ := emp_exp_typ(); 
    v_exp emp_exp_typ; 
BEGIN 
    v_empid := emp_id_typ(101, 102, 52, 100, 206); 
    -- moved this call up, without indexing 
    exp_sp(v_empid, v_exp); 
    -- better to use either 1..count, or first..last; don't mix them 
    -- FOR i IN v_empid.FIRST..v_empid.COUNT 
    FOR i IN v_empid.FIRST..v_empid.LAST 
    LOOP 
    --exp_sp(v_empid(i), v_exp(i)); 
    -- fixed call to dbms_output 
    dbms_output.put_line(v_empid(i) ||': '|| v_exp(i)); 
    END LOOP; 
END; 
/

101: 28 
102: 25 
52: -1 
100: 30 
206: 24 


PL/SQL procedure successfully completed. 

は、私はそれが表にでないように、第3の変数を印刷する必要はありません。

あなたはマジックナンバーのためv_exp値をテストすることができます(より安全であるかnull、が、手順が、そのために少し変更する必要がある)、そして唯一のあなたが必要とする結果を印刷:

... 
    FOR i IN v_empid.FIRST..v_empid.LAST 
    LOOP 
    IF v_exp(i) != -1 THEN 
     dbms_output.put_line(v_empid(i) ||': '|| v_exp(i)); 
    END IF; 
    END LOOP; 
... 

これは次のようになります:

101: 28 
102: 25 
100: 30 
206: 24 

PL/SQL procedure successfully completed. 
+0

テーブルにないので、3番目の変数を出力する必要はありません。 3番目の変数から次の変数を出力する必要があります。 –

+0

OKですので、 'v_exp'の値をチェックし、-1の場合はループを'続行します(魔法の番号ではなくヌルを使用する場合はnull)。 –

関連する問題