2016-12-27 6 views
0

私は、以下の手順を実行しようとしていますため、無効なSQL文が、エラーを取得保管(ORA-00900:無効なSQL文)ORA-00900:Oracleの手順

CREATE OR REPLACE PROCEDURE RESETUSERSESSION (run IN VARCHAR2) 
IS  
    cursor usersessiondetail_cur IS  
      SELECT usd.CLIENTID,usd.OPERID,usd.REGISTER,usd.MACHINE_ID,usd.SESSIONNUMBER 
      FROM cashiering_dev.CSH_USER usr, cashiering_dev.CSH_USERSESSIONDETAIL usd 
      WHERE usr.clientid = usd.clientid 
      AND usr.operid = usd.operid 
      AND usr.register = usd.register 
      AND usr.machine_id = usd.machine_id 
      AND usr.sessionnumber = usd.sessionnumber 
      AND usr.Machine_ID = 'basrytest' 
      AND usd.LOGOFFDATETIME IS NULL; 


BEGIN 
     OPEN usersessiondetail_cur;  

     FOR vItems in usersessiondetail_cur 
     LOOP 
      EXECUTE IMMEDIATE 'UPDATE csh_UserSessionDetail 
         SET ClientID =vItems.CLIENTID 
         WHERE ClientID =vItems.CLIENTID 
         AND OperID =vItems.OPERID 
         AND Register =vItems.REGISTER 
         AND Machine_ID =vItems.MACHINE_ID 
         AND SessionNumber =vItems.SESSIONNUMBER';      
     END LOOP; 

     CLOSE usersessiondetail_cur; 



END; 
+1

'cursor for'ループを使用しているときにカーソルを明示的にオープン/クローズしないでください(' OPEN usersessiondetail_cur')。この場合、動的SQL(「UPDATE」ステートメント)を使用する必要は全くありません。 –

+1

動的SQLはまったく役に立たない。なぜあなたはそれを使用していますか? –

+1

プロシージャをコンパイルしようとしてエラーが発生しましたか、実際に実行しようとしていますか?いずれにせよ、あなたはどのようにしていますか?どのクライアントやコマンドなど?あなたが得る完全なエラースタックは何ですか? (なぜ、あなたはただ一つの更新をするのではなく、なぜループを使用していますか?あなたの 'run'パラメータは何ですか?) –

答えて

1

あなたのSQLが無効なカーソルの投影名理由動的SQL文字列が実行されるときに範囲内にありません。あなたは、このようなプレースホルダを使用する必要があります。

FOR vItems in usersessiondetail_cur 
    LOOP 
     EXECUTE IMMEDIATE 'UPDATE csh_UserSessionDetail 
        SET ClientID = :p1 
        WHERE ClientID = :p2 
        AND OperID = :p3 
        AND Register = :p4 
        AND Machine_ID = :p5 
        AND SessionNumber = :p6' 
      using vItems.CLIENTID 
       , vItems.CLIENTID 
       , vItems.OPERID 
       , Items.REGISTER 
       , vItems.MACHINE_ID 
       , vItems.SESSIONNUMBER;      
    END LOOP; 

パラメータが名前ではない位置で渡されますので、あなたの動的なコードが無名PL/SQLブロックまたはCALL文ではないので、あなたが二回vItems.CLIENTIDを渡す必要があります。 Find out more

その他の観測

  • まず第一に、このSQLの動的実行を実装する必要は全くありません。
  • OPENおよびCLOSEカーソル・ステートメントは、FORカーソル・ループでは使用されません。
  • このクエリでは、明示的なカーソル宣言は必要ありません。
  • カーソルループを使用した行単位の行UPDATEは、セットベースのUPDATEステートメントと比較して不都合にも無駄です。
  • プロシージャでは、runパラメータを使用しません。
  • ...ただし、カーソルにはMACHINE_IDのハードコード文字列があります。
  • 最後に、CLIENT_ID = CLIENT_IDを設定するため、UPDATEステートメントはテーブルの状態を実際に変更しないため、プロシージャ全体が無意味です。

それ以外は、すべて問題ありません。

私は、これをビジネスロジックの実装ではなく動的SQLの使用方法を理解するためのテストとして書いていると仮定します。しかし、それがテストであっても、何かをする適切なコードを書く方が良いです。特にStackOverflowで他の人とコードを共有しているとき。非常に多くの問題があるコードを掲示することは、潜在的な回答者がどの課題に取り組むべきか分からないため気を散らす。

0

FORループだけではるかに簡単なアプローチです。この場合、Open CloseカーソルはOracleで内部的に処理されるため、必要ありません。また、クライアントIDを再度更新する必要性についても理解していません。 ClauseのどこにClient IDを選択している場合、Updatingの意味はありません。とにかくお楽しみください:)