36

これまで原因を特定できなかったOracleの問題に遭遇しました。以下のクエリはOracleSQLDeveloperで機能しますが、.NETで実行すると次のようにスローされます。

ORA-01008:すべての変数がバインドされているわけではありません

私はもう試した:

  • lot_priority(Varchar2またはint32)のOracleデータ型を変更します。
  • lot_priority(stringまたはint)の.NETデータ型を変更します。
  • 1つのバインド変数名がクエリで2回使用されます。これは、複数の場所で同じバインドされた変数を使用する他のクエリでは問題になりませんが、2番目のインスタンスを異なる:nameで独自の変数にして、別々にバインドしようとしたことを確認してください。
  • 変数をバインドするいくつかの異なる方法(コメント付きのコードを参照;その他も参照)。
  • bindByName()呼び出しを移動します。
  • バインドされた各変数をリテラルに置き換えます。問題の原因となる2つの別々の変数(:lot_priと:lot_priprc)があります。2つの間に思い出せない小さな変更がいくつかありました。リテラルに変更するとクエリは機能しましたが、バインディングで機能する必要があります。

クエリとコードが続きます。変数名は、無実の人を保護するために変更されました。

SELECT rf.myrow floworder, rf.stage, rf.prss,
rf.pin instnum, rf.prid, r_history.rt, r_history.wt
FROM
(
    SELECT sub2.myrow, sub2.stage, sub2.prss, sub2.pin, sub2.prid
    FROM (
        SELECT sub.myrow, sub.stage, sub.prss, sub.pin,
            sub.prid, MAX(sub.target_rn) OVER (ORDER BY sub.myrow) target_row
            ,sub.hflag
        FROM (
            WITH floc AS 
            (
                SELECT flow.prss, flow.seq_num
                FROM rpf@mydblink flow
                WHERE flow.parent_p = :lapp
                AND flow.prss IN (
                    SELECT r_priprc.prss
                    FROM r_priprc@mydblink r_priprc
                    WHERE priprc = :lot_priprc
                )
                AND rownum = 1
            )
            SELECT row_number() OVER (ORDER BY pp.seq_num, rpf.seq_num) myrow,
                rpf.stage, rpf.prss, rpf.pin,
                rpf.itype, hflag,
            CASE WHEN rpf.itype = 'SpecialValue'
                THEN rpf.instruction
                ELSE rpf.parent_p
            END prid,
            CASE WHEN rpf.prss = floc.prss
                AND rpf.seq_num = floc.seq_num
                THEN row_number() OVER (ORDER BY pp.seq_num, rpf.seq_num)
            END target_rn
            FROM floc, rpf@mydblink rpf
            LEFT OUTER JOIN r_priprc@mydblink pp
                ON (pp.prss = rpf.prss)
            WHERE pp.priprc = :lot_priprc
            ORDER BY pp.seq_num, rpf.seq_num
        ) sub
    ) sub2
    WHERE sub2.myrow >= sub2.target_row
    AND sub2.hflag = 'true'
) rf
LEFT OUTER JOIN r_history@mydblink r_history
ON (r_history.lt = :lt
    AND r_history.pri = :lot_pri
    AND r_history.stage = rf.stage
    AND r_history.curp = rf.prid
)
ORDER BY myrow

public void runMyQuery(string lot_priprc, string lapp, string lt, int lot_pri) {
Dictionary<int, foo> bar = new Dictionary<int, foo>();
using(var con = new OracleConnection(connStr)) {
    con.Open();

    using(var cmd = new OracleCommand(sql.rtd_get_flow_for_lot, con)) { // Query stored in sql.resx
        try {
            cmd.BindByName = true;
            cmd.Prepare();
            cmd.Parameters.Add(new OracleParameter("lapp", OracleDbType.Varchar2)).Value = lapp;
            cmd.Parameters.Add(new OracleParameter("lot_priprc", OracleDbType.Varchar2)).Value = lot_priprc;
            cmd.Parameters.Add(new OracleParameter("lt", OracleDbType.Varchar2)).Value = lt;
            // Also tried OracleDbType.Varchar2 below, and tried passing lot_pri as an integer
            cmd.Parameters.Add(new OracleParameter("lot_pri", OracleDbType.Int32)).Value = lot_pri.ToString();
            /*********** Also tried the following, more explicit code rather than the 4 lines above: **
            OracleParameter param_lapp
                = cmd.Parameters.Add(new OracleParameter("lapp", OracleDbType.Varchar2));
            OracleParameter param_priprc
                = cmd.Parameters.Add(new OracleParameter("lot_priprc", OracleDbType.Varchar2));
            OracleParameter param_lt
                = cmd.Parameters.Add(new OracleParameter("lt", OracleDbType.Varchar2));
            OracleParameter param_lot_pri
                = cmd.Parameters.Add(new OracleParameter("lot_pri", OracleDbType.Varchar2));
            param_lapp.Value = lastProcedureStackProcedureId;
            param_priprc.Value = lotPrimaryProcedure;
            param_lt.Value = lotType;
            param_lot_pri.Value = lotPriority.ToString();
            //***************************************************************/
            var reader = cmd.ExecuteReader();
            while(reader.Read()) {
                // Get values from table (Never reached)
            }
        }
        catch(OracleException e) {
            //     ORA-01008: not all variables bound
        }
    }
}

Oracleがすべての変数がバインドされているわけではないと主張するのはなぜですか?

4

8 に答える 8

19

エラーなしでクエリを実行する方法を見つけましたが、根本的な原因を本当に理解せずに「解決策」と呼ぶのをためらっています。

これは、実際のクエリの冒頭によく似ています。

-- Comment
-- More comment
SELECT rf.flowrow, rf.stage, rf.process,
rf.instr instnum, rf.procedure_id, rtd_history.runtime, rtd_history.waittime
FROM
(
    -- Comment at beginning of subquery
    -- These two comment lines are the problem
    SELECT sub2.flowrow, sub2.stage, sub2.process, sub2.instr, sub2.pid
    FROM ( ...

サブクエリの先頭にある上記の 2 番目のコメント セットが問題でした。削除すると、クエリが実行されます。他のコメントは結構です。次の行は SELECT であるため、これは、次の行がコメント化される原因となる不正または欠落した改行の問題ではありません。選択が欠落していると、「すべての変数がバインドされていません」とは異なるエラーが発生します。

私が周りに尋ねたところ、これに遭遇した 1 人の同僚が見つかりました -- クエリの失敗を引き起こすコメント -- 数回。これがどのように原因になるか知っている人はいますか?DBMS がコメントに対して最初に行うことは、ヒントが含まれているかどうかを確認し、含まれていない場合は解析中に削除することだと私は理解しています。異常な文字 (文字とピリオドのみ) を含まない通常のコメントで、どのようにエラーが発生するのでしょうか? 奇妙な。

于 2011-09-24T23:41:32.250 に答える
8

:lot_priprc バインディング変数への 2 つの参照があります。変数の値を 1 回だけ設定し、両方の場所でバインドする必要があるはずですが、これが機能せず、各コピーを別の変数。痛みはありますが、うまくいきました。

于 2011-09-21T13:17:48.010 に答える
2

チャールズのコメント問題について: さらに悪いことに、

:p1 = 'TRIALDEV'

コマンドパラメータを介して、実行します

select T.table_name as NAME, COALESCE(C.comments, '===') as DESCRIPTION
from all_all_tables T
Inner Join all_tab_comments C on T.owner = C.owner and T.table_name = C.table_name
where Upper(T.owner)=:p1
order by T.table_name

558 line(s) affected. Processing time: 00:00:00.6535711

リテラル文字列を === から --- に変更する場合

select T.table_name as NAME, COALESCE(C.comments, '---') as DESCRIPTION
[...from...same-as-above...]

ORA-01008: not all variables bound

両方のステートメントは、SQL Developer で正常に実行されます。短縮コード:

            Using con = New OracleConnection(cs)
                con.Open()
                Using cmd = con.CreateCommand()
                    cmd.CommandText = cmdText
                    cmd.Parameters.Add(pn, OracleDbType.NVarchar2, 250).Value = p
                    Dim tbl = New DataTable
                    Dim da = New OracleDataAdapter(cmd)
                    da.Fill(tbl)
                    Return tbl
                End Using
            End Using

.Net 4.61 プラットフォームで VS2015 のデフォルト設定で Oracle.ManagedDataAccess.dll バージョン 4.121.2.0 を使用します。

そのため、コール チェーンのどこかに、commandText 内の -- で始まる 1 行のコメントを少し積極的に探すパーサーが存在する可能性があります。しかし、これが正しいとしても、「すべての変数がバインドされていません」というエラー メッセージは、少なくとも誤解を招くものです。

于 2016-01-04T18:35:39.403 に答える
1

Udemyコースを受講中に、以下にリストされたステートメントを実行すると同じエラーが発生したため、ヘルプを探してここに来ました:

INSERT INTO departments (department_id, department_name)
                  values( &dpet_id, '&dname');  

以前は、置換変数を使用してステートメントを実行できました。変数の再作成中にサーバーが何らかのしきい値に達する可能性についての Charles Burns のコメントにより、ログアウトして SQL Developer を再起動するように促されました。再度ログインした後、ステートメントは正常に実行されました。

私のように範囲が限られている問題を抱えてここで冒険している他の人のために共有したいと思いました。

于 2018-10-01T02:17:23.033 に答える
0

レガシーアプリケーションでも同様の問題がありましたが、「--」は文字列パラメーターでした。

元。:

Dim cmd As New OracleCommand("INSERT INTO USER (name, address, photo) VALUES ('User1', '--', :photo)", oracleConnection)
Dim fs As IO.FileStream = New IO.FileStream("c:\img.jpg", IO.FileMode.Open)
Dim br As New IO.BinaryReader(fs)
cmd.Parameters.Add(New OracleParameter("photo", OracleDbType.Blob)).Value = br.ReadBytes(fs.Length)
cmd.ExecuteNonQuery() 'ここで ORA-01008 がスローされます

アドレス パラメータ値「--」を「00」などに変更すると機能します。

于 2016-06-08T16:58:05.363 に答える