2017-03-23 10 views
0

次のPL/SQLを書いて、私に与えられた式を動的に文字列として実行しました。数式からの最終出力は、o_変数に返されると期待していた19を返す必要があります。動的PL/SQLブロックを実行して合計を実行し、値を返す

実際にコードはエラーなく実行されますが、私が期待していた結果は得られません。 DBMS_SQLパッケージを正しく使用していますか?

この問題を複雑にする要因は、入力文字列(または数式)に含まれるバインド変数の数がわからないことです。したがって、EXECUTE IMMEDIATEは、バインディングが必要な変数の数を事前に知っていることを前提としているため、動的PL/SQLを実行する戦略を使用することはできません。

正しい方法で問題に近づいていますか?これを行うより良い方法はありますか?

DECLARE 
    cur_ INTEGER; 
    r_ NUMBER; 
    str_ VARCHAR2(2000) := 'BEGIN :out := :x * 3 + :y; END;'; 
    x_ NUMBER := 3; 
    y_ NUMBER := 10; 
    o_ NUMBER; 
BEGIN 
    cur_ := Dbms_SQL.open_cursor; 
    Dbms_SQL.Parse (cur_, str_, Dbms_SQL.Native); 
    Dbms_SQL.Bind_Variable (cur_, ':out', o_); 
    Dbms_SQL.Bind_Variable (cur_, ':x', x_); 
    Dbms_SQL.Bind_Variable (cur_, ':y', y_); 
    r_ := Dbms_SQL.Execute (cur_); 
    Dbms_SQL.Close_Cursor (cur_); 
    Dbms_Output.Put_Line ('Your variables: ' || x_ || ', ' || y_ || ', and out: ' || o_ || ', and R: ' || r_); 
END; 
+0

文字列は固定文字列ですか。そうでない場合は、[この質問](http://stackoverflow.com/questions/5209981/use-of-bind-variable)の回答にあるもののようなものを使用することができます。 – Nitish

+0

@Nitishあなたが何を言及しているかわからない。私はそのページに私が求めている質問に近づく何かを見つけることができません。 – cartbeforehorse

答えて

3

あなたはDBMS_SQL.VARIABLE_VALUEコールを見逃しました。

DECLARE 
    cur_ INTEGER; 
    r_ NUMBER; 
    str_ VARCHAR2(2000) := 'BEGIN :out := :x * 3 + :y; END;'; 
    x_ NUMBER := 3; 
    y_ NUMBER := 10; 
    o_ NUMBER; 
BEGIN 
    cur_ := DBMS_SQL.OPEN_CURSOR; 
    DBMS_SQL.PARSE (cur_, str_, DBMS_SQL.NATIVE); 
    DBMS_SQL.BIND_VARIABLE (cur_, ':out', o_); 
    DBMS_SQL.BIND_VARIABLE (cur_, ':x', x_); 
    DBMS_SQL.BIND_VARIABLE (cur_, ':y', y_); 
    r_ := DBMS_SQL.EXECUTE (cur_); 
    DBMS_SQL.VARIABLE_VALUE(cur_, ':out', o_); 
    DBMS_SQL.CLOSE_CURSOR (cur_); 
    DBMS_OUTPUT.PUT_LINE ('Your variables: ' || x_ || ', ' || y_ || ', and out: ' || o_ || ', and R: ' || r_); 
END; 

Your variables: 3, 10, and out: 19, and R: 1 
1

「デュアルからあなたの計算を選択」を使用して試してください。結果の行をフェッチして列の値を取得してください。

declare 
    res number; 
    cur_ integer; 
    r_ number; 
    str_ varchar2(2000) := 'select :x * 3 + :y from dual'; 
    x_ number := 3; 
    y_ number := 10; 
    o_ number; 
begin 
    cur_ := dbms_sql.open_cursor; 
    dbms_sql.parse(cur_, str_, dbms_sql.native); 
    dbms_sql.bind_variable(cur_, ':x', x_); 
    dbms_sql.bind_variable(cur_, ':y', y_); 
    dbms_sql.define_column(cur_, 1, o_); 
    r_ := dbms_sql.execute(cur_); 
    res := dbms_sql.fetch_rows(cur_); -- Fetch only the first row, no loop required 
    dbms_sql.column_value(cur_, 1, o_); 
    dbms_sql.close_cursor(cur_); 
    dbms_output.put_line('Your variables: ' || x_ || ', ' || y_ || ', and out: ' || o_ || ', and R: ' || r_); 
end; 
+1

'dbms_sql.execute()'と 'dbms_sql.fetch_rows'の代わりに、単一の' dbms_sql.EXECUTE_AND_FETCH() ' –

+0

を使用して、毎日何かを学ぶことができます。 – Rene

+0

@Rene私はこの問題を寝る前に投稿しました。私が目を覚ましたとき、私はこの解決策も考えました(私はコードを夢見ていたに違いない)。それは実際に働きます(もちろん、ユーザーからの入力文字列を変更する必要はありません)。しかし、私はこのソリューションを「受け入れられた答え」とマークするつもりはないと思います。なぜなら、Wernfriedのソリューションフォームが直接質問に答えるからです。しかし、ちょっと箱の外側に考えてみると+1。あなたのアイデアは高く評価されました – cartbeforehorse

関連する問題