2011-08-02 1 views
1

execute immediateの動的SQL文を作成するときに、文字列連結の代わりにバインド変数を使用したいとします。私はabretのためのバインド変数を使用することができますが、私はfためにバインドしようとしたとき、私はORA-06502: PL/SQL: numeric or value error: character to number conversion errorを取得する以下の例では実行即時ステートメントでバインド変数を使用できないのはなぜですか?

。どうして私はバインドすることができますf

私は11.2.0.1.0を使用しています。あなたはvarchar2としてfを宣言しているため

create or replace function so4fun (
    a in number, 
    b in number, 
    f in varchar2 
) return number as 
    decl constant varchar2(32767) := 
    'declare a constant number := :a; b constant number := :b;'; 
    stmt varchar2(32676); 
    ret number; 
begin 
    /* This one works: */ 
    stmt := decl || ' begin :result := ' || f || '; end;'; 
    execute immediate stmt using in a, in b, out ret; 

    /* But why this one doesn't ? 

    stmt := decl || ' begin :result := :f; end;'; 
    execute immediate stmt using in a, in b, out ret, in f; 

    This doesn't work either: 

    stmt := decl || ' tmp number; begin tmp := :f; :result := tmp; end;'; 
    execute immediate stmt using in a, in b, in f, out ret; 

    Both are giving me ORA-06502: PL/SQL: numeric or value error: character to 
    number conversion error */ 

    return ret; 
end; 
/
show errors 

/* expected result when a = 1, b = 2 is 1.5 */ 
select so4fun(1, 2, '(a + b)/b') from dual; 

drop function so4fun; 
+0

私は彼の答えをより包括的かつコンパクトに見ているので、私はCodoの答えを選択しました。しかし、私もRay Toalの答えが役に立つと分かりました。私は彼の答えから自分の問題への答えも結論づけることができました。私はそれらの両方に多くのupvotesを願っています! – user272735

答えて

2

バインド変数はバインディング変数用であり、バインドコード用ではありません。 Oracleは、問合せやブロック・ブロックをコンパイルしてキャッシュし、異なるパラメータで複数回実行できるという考え方です。

ただし、計算された数式を置き換えるためにパラメータバインディングを使用しようとします。これはコードブロックのコンパイルとキャッシングを防ぎ、したがってサポートされません。

さらに、現在の構文では表現できません。 Oracleがtmp := :fと表示した場合、変数tmpにパラメータfを簡単に割り当てたいと考えています。関数を評価する必要はありません。

解決策を試してみてください。それは結局働く。

1

エラーが発生しますが、あなたは、あなたのコメントアウトされたセクションに次のように書かれている:あなたはに「文字」の値を代入しようとし

tmp number; begin tmp := :f ... 

します数値が必要な変数。あなたはまた、数値を期待する関数結果にfを割り当てようとしました。

これは文字列の連結であるため、状況は||で問題なく動作します。

varchar2を数値(TO_NUMBER(f))に変換する必要があります。または、おそらく、パラメータfをvarchar2ではなく数値として受け入れるようにprocを記述する必要があります。

+0

Oracleは私に賛成し、バインド変数が正しい種類の型であることをチェックしていますか? 'f'の場合、' begin:result:=(a + b)/ b;のような文を生成することを意図しています。 ':result'は数値に結び付けられ、'(a + b)/ b'はバインディングが行われるときにvarchar2なので失敗します? – user272735

+2

あなたは 'f'をvarchar2' "(a + b)/ b" 'にしたいですか?つまり、 'f'は評価したい文字列のテキストですか?その場合、バインディングは適切ではないので、文字列連結を行う必要があります。または、ここに役立つ情報があれば参照してください。http://asktom.oracle.com/pls/asktom/f?p=100:11:4121852961219206:::P11_QUESTION_ID:1179235402134 –

関連する問題