3

コードを注意深くチェックしたにもかかわらず、次のエラーが発生します。何が足りないのかわかりません。

LINE/COLエラー


31/1 PLS-00103:次のいずれかが予想されるときに、記号「END」が検出されました。

コード:

CREATE OR REPLACE PROCEDURE sp_ssjm_newworkorder
(   workorderno IN NUMBER,
company     IN CHAR,
attention   IN CHAR,
datedue     IN DATE,
loggedby    IN CHAR
)

AS  id     NUMBER;
today         DATE:=SYSDATE;
BEGIN
SELECT  client_id   --grab client_id
INTO id 
FROM    ssjm_client
WHERE ssjm_client.name=company;

IF id IS NULL THEN  --check if client exists by checking if client_id is there
    dbms_output.put_line('Please create client first');
    GOTO the_end;
ELSE
    INSERT INTO ssjm_workorder      VALUES(workorderno,workorderno,company,loggedby,attention,'Received',today,datedue,id);
END IF;

EXCEPTION
    WHEN OTHERS THEN
    raise_application_error(-20999,'An error occured in' ||
        SQLCODE || '-ERROR-' || SQLERRM);

<<the_end>>

END sp_ssjm_newworkorder;
4

1 に答える 1

4

コードには注意が必要な箇所がいくつかあります。

  1. このエラーが発生する理由は、ラベル をセクション<<the_end>>の前に配置する必要があるためです。EXCEPTION
  2. ラベルの後に演算子が必要です。したがって、ストアドプロシージャの最後にジャンプし、他のアクションを必要としない場合は、NULL演算子を使用する必要があります。

そのためには、コードは次のようになります。

IF id IS NULL THEN  --check if client exists by checking if client_id is there
    dbms_output.put_line('Please create client first');
    GOTO the_end;
ELSE
    INSERT INTO ssjm_workorder
 VALUES(workorderno,workorderno,company,loggedby
       ,attention,'Received',today,datedue,id);
END IF;

<<the_end>>
NULL;

EXCEPTION
    WHEN OTHERS THEN
    raise_application_error(-20999,'An error occured in' ||
        SQLCODE || '-ERROR-' || SQLERRM);
END sp_ssjm_newworkorder;

無条件の分岐は絶対に避けてください。演算子を使用するGOTOことは、非常に、非常に良い習慣ではありません。それは読みやすさを殺します、そのようなコードはデバッグするのが難しいです。それはあなたとあなたの後にそのコードを見るすべての人に頭痛の種を引き起こします。さらに、クエリの場合

SELECT  client_id   --grab client_id
INTO id 
FROM    ssjm_client
WHERE ssjm_client.name=company;

行を返さない場合、例外NO_DATA_FOUNDがすぐに発生し、コードの実行が停止します。したがって、IF id IS NULL THEN状態が評価されることはありません。その条件を削除し、コードのセクションにNO_DATA_FOUND例外ハンドラーを追加することで、コードを書き直すことができます。EXCEPTIONそしてもちろん、@ RobvanWijkがコメントで正しく指摘したように

ただし、コードはさらにクリーンアップできます。今日の変数は削除でき、WHENOTHERSは確実に削除する必要があります。現在のように、エラーを詳細なしでより長いエラーメッセージに変換するだけであり、最も重要なのは、実際のエラーが発生した行番号を偽装することです。

today変数は必要なく、ステートメントの句でSYSDATE直接使用でき、削除することもできます。valuesinsertWHEN OTHERS

CREATE OR REPLACE PROCEDURE sp_ssjm_newworkorder
(
workorderno IN NUMBER,
company     IN CHAR,
attention   IN CHAR,
datedue     IN DATE,
loggedby    IN CHAR
)
AS  
  id     NUMBER;
BEGIN
  SELECT client_id   --grab client_id
    INTO id
    FROM ssjm_client
   WHERE ssjm_client.name=company;

    INSERT INTO ssjm_workorder      
      VALUES(workorderno,workorderno,company,loggedby
            ,attention,'Received',SYSDATE,datedue,id);

EXCEPTION
    when NO_DATA_FOUND
    then dbms_output.put_line('Please create client first');
END sp_ssjm_newworkorder;
于 2012-11-03T12:40:56.677 に答える