Oracle "ORA-01008: не все переменные связаны" Ошибка w/Параметры

Впервые я столкнулся с Oracle, и мне трудно понять, почему я получаю эту ошибку.

Я использую Oracle ODT.NET w/С# со следующим кодом в запросе where 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 (...." ), запрос завершается успешно.

Почему запрос выполнялся нормально, если я запрашиваю только два параметра, но не с тремя? Ошибка, которую я получаю, даже не имеет смысла

Ответ 1

Поставщик ODP.Net из oracle использует привязку по позиции по умолчанию. Чтобы изменить поведение для привязки по имени. Установите свойство BindByName в true. Чем вы можете отклонить двойное определение параметров.

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

Ответ 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");

Конечно, это правда с Native Dynamic SQL в PL/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.

Ответ 3

Вы также можете рассмотреть возможность удаления дубликатов имен параметров в вашем Sql, изменив ваш Sql на

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

а затем, чтобы ваш клиент предоставил "%" для любого значения VarB вместо null. В некотором смысле я считаю, что это более естественно.

Вы также можете изменить Sql на

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