2017-01-27 39 views
0

以下のコード・セクションを実行しようとしましたが、ORA-00904エラーが発生しました。ORA-00904 - "NORM":動的SQLの無効な識別子文字列

例外が線で上昇さ
Declare 
i_status varchar2(4) := 'NORM'; 
vsql varchar2(4000); 
... 
... 
Begin 
... 
...<Part of larger dynamic sql> 
    If i_status is not null Then 
    vSql := vSql || ' And account.astatus = ' ||i_status|| ''; 
    End if; 

execute immediate (vSql) into tmp,ssn; 

<Do something with tmp, ssn> 

End; 

エラー ORA-00904と "即時実行" - "NORM":無効な識別子

列account.astatusは、char(4バイト)

I型を持ちます文字列変数NORMをwhere節に渡そうとしていて、引用符を追加しないという問題があるとします。この問題を回避するにはどうすればよいですか?

ありがとうございました。

答えて

4

単純な答えは、バインド変数を使用することです。つまり、変数をダイナミックSQLにハードコードするときにあなた自身が開くSQLインジェクションの厄介な問題を回避できます。また、動的SQLが現在欠落している文字列を一重引用符で囲む方法を検討する必要もありません。

は、バインド変数を使用して、あなたのコードは次のようになります。あなたが簡単にあなたのコードを掘り下げ、問題はそれを実行する前に、あなたのVSQLを印刷して存在する場合にチェックすることができ

Declare 
    i_status varchar2(4) := 'NORM'; 
    vsql varchar2(4000); 
    ... 
    ... 
Begin 
    ... 
    ...<Part of larger dynamic sql> 

    If i_status is not null Then 
    vSql := vSql || ' And account.astatus = :i_status'; 
    End if; 

    execute immediate (vSql) into tmp,ssn using i_status; 

    <Do something with tmp, ssn> 

End; 
+0

ありがとうございます。魅力のように働いた。 – MrM

4

Declare 
    i_status varchar2(10) := 'NORM'; 
    vsql varchar2(4000):= 'Select * from dual where 1=3'; 

    Begin 

     If i_status is not null Then 
     vSql := vSql || ' And account.astatus = ' ||i_status|| ''; 
     End if; 

     dbms_output.put_line(vSql); 

     --execute immediate (vSql) into tmp,ssn;   

    End; 

あなたはこのブロックを実行すると、あなたが示して生成取得される声明見ることができます:デュアルから

選択*を1 = 3、account.astatus = NORM

今度は、account.astatus = NORMが正しくないため、次のように置き換えることができます。

i_status varchar2(10) := '''NORM'''; 

または使用してQの引用:Boneistが述べたにもかかわらず何

i_status varchar2(10) := q'['NORM']'; 

は、SQLインジェクションを避ける最善の方法です。

関連する問題