web-dev-qa-db-ja.com

Oracle「ORA-01008:すべての変数がバインドされていない」エラーパラメータ付き

Oracleを扱ったのはこれが初めてであり、このエラーを受け取った理由を理解するのに苦労しています。

OracleのODT.NET w/C#とクエリのwhere句で次のコードを使用しています。

WHERE table.Variable1 = :VarA
  AND (:VarB IS NULL OR table.Variable2 LIKE '%' || :VarB || '%')
  AND (:VarC IS NULL OR table.Variable3 LIKE :VarC || '%')

そして、私は次のようにパラメータ値を追加しています:

cmd.Parameters.Add("VarA", "24");
cmd.Parameters.Add("VarB", "test");
cmd.Parameters.Add("VarC", "1234");

このクエリを実行すると、サーバーは以下を返します。

ORA-01008: not all variables bound 

「AND(....」行のいずれかをコメント化すると、クエリは正常に完了します。

3つのパラメーターではなく2つのパラメーターのみでクエリを実行している場合、なぜクエリが正常に実行されるのですか?私が受け取っているエラーは意味がありません

30
John

OracleのODP.Netプロバイダーは、デフォルトとして位置によるバインドを使用します。名前でバインドするように動作を変更します。プロパティ BindByName をtrueに設定します。パラメーターの二重定義を却下できるよりも。

using(OracleCommand cmd = con.CreateCommand()) {
    ...
    cmd.BindByName = true;
    ...
}
44
Christian13467

一見簡単そうに思えますが、同じバインド変数を2回使用する場合は、2回設定する必要があると思います。

cmd.Parameters.Add("VarA", "24");
cmd.Parameters.Add("VarB", "test");
cmd.Parameters.Add("VarB", "test");
cmd.Parameters.Add("VarC", "1234");
cmd.Parameters.Add("VarC", "1234");

確かに、PL/SQLのネイティブダイナミックSQLにはそうです。

SQL> begin
  2     execute immediate 'select * from emp where ename=:name and ename=:name'
  3     using 'KING';
  4  end;
  5  /
begin
*
ERROR at line 1:
ORA-01008: not all variables bound


SQL> begin
  2     execute immediate 'select * from emp where ename=:name and ename=:name' 
  3     using 'KING', 'KING';
  4  end;
  5  /

PL/SQL procedure successfully completed.
24
Tony Andrews

また、Sqlを

table.Variable2 LIKE '%' || :VarB || '%'

そして、クライアントにnullではなくVarBの任意の値に「%」を提供させます。ある意味では、これはもっと自然だと思います。

Sqlを次のように変更することもできます

table.Variable2 LIKE '%' || IfNull(:VarB, '%') || '%'
2
Hugh Jones