Когда параметризованный запрос выполняется, он, похоже, не имеет значения для параметра

Следующий код, насколько я понимаю, должен создать параметризованный оператор и добавить значение к этому параметру. Параметр «@exp» и добавляемое к нему значение определяются пользовательским вводом. Я сохраняю пользовательский ввод в String exp; (не мой выбор, кто-то другой написал большую часть этой функции).

SQl_Command.CommandText = "SELECT COUNT(*) As MyCount FROM members WHERE ([Primary Exp] = '@exp') AND ([Approved] = 'True') OR ([Approved] = 'True') AND ([Secondary Exp] = '@exp')";
SQl_Command.Parameters.Add("@exp", SqlDbType.NVarChar, 255);
SQl_Command.Parameters["@exp"].Value = exp;

Желаемый результат для моего теста — 16, но этот запрос возвращает 0. Запрос работает при запуске из SQL Server 2008 и выглядит следующим образом.

SELECT COUNT(*) As MyCount 
FROM members 
WHERE ([Primary Exp] = 'Risk Management') 
  AND ([Approved] = 'True') OR ([Approved] = 'True') 
  AND ([Secondary Exp] = 'Risk Management')

Я должен иметь возможность использовать Response.Write(SQl_Command.CommandText);, где я выбрал «Управление рисками», и параметризованный запрос должен распечатать:

SELECT COUNT(*) As MyCount 
FROM members 
WHERE ([Primary Exp] = 'Risk Management') 
  AND ([Approved] = 'True') OR ([Approved] = 'True') 
  AND ([Secondary Exp] = 'Risk Management')`

Однако это не так. Остается @exp, как если бы это было значением, с которым я хотел сравнить [Primary Exp] и [Secondary Exp]. Это правильно?

Я видел несколько способов сделать это, но в целом я следовал примеру здесь

Я не думаю, что это проблема, но именно так я использую запрос.

SQl_Reader = SQl_Command.ExecuteReader();
int numRows = 0;
while(SQl_Reader.Read()){
    numRows = Convert.ToInt32(SQl_Reader["MyCount"]);
}

Я уверен, что это что-то простое, что мне не хватает, но я не смог этого увидеть.


person TheDude    schedule 21.08.2013    source источник
comment
Ваше ожидание неверно: использование параметров не означает, что код SQL на стороне клиента заменит эти параметры их фактическими значениями. Параметры отправляются как параметры на сервер SQL Server, включая их значения в списке значений. Так оно и есть, и так оно и должно быть - если вы ожидали, что параметры будут заменены их фактическими значениями до того, как запрос будет отправлен на SQL Server, вы ошибались.   -  person marc_s    schedule 22.08.2013


Ответы (2)


Здесь вы имеете дело с переменными, объекты SQL не просто выполняют «более безопасный» поиск и замену. Измените свой код на:

SQl_Command.CommandText = "SELECT COUNT(*) As MyCount FROM members WHERE 
        ([Primary Exp] = @exp) AND ([Approved] = 'True') OR
        ([Approved] = 'True') AND ([Secondary Exp] = @exp)";

и вы должны обнаружить, что теперь получили правильное значение; с вашей исходной версией он буквально искал строку '@exp'.

Обратите внимание, что параметры SQL и сама команда объединяются только во время выполнения, как часть вызова SQL Server. Поэтому, когда вы видите, что @exp все еще отображается в CommandText даже после добавления параметров, это на самом деле правильно.

person Adrian Wragg    schedule 21.08.2013

Когда вы запускаете параметризованный запрос через одного из поставщиков .NET SQL Server, запрос сохраняет его параметризованную форму на всем пути к серверу. Если бы вы запустили SQL Profiler во время выполнения вашего запроса, вы бы увидели событие «RPC», которое выполняет ваш запрос, заполняя параметры по пути.

RPC — это один из способов для клиента SQL напрямую выполнить хранимую процедуру по имени, в отличие от выполнения инструкции T-SQL в виде текста. Вместо того, чтобы отправлять вашу команду SQL как T-SQL, она отправляется в форме вызова RPC к «sp_executesql», при этом ваш запрос и последующие параметры сами отправляются как параметры для sp_executesql. Таким образом, ваш запрос будет выполняться примерно так:

sp_executesql "SELECT COUNT(*) As MyCount FROM members WHERE ([Primary Exp] = '@exp') AND ([Approved] = 'True') OR ([Approved] = 'True') AND ([Secondary Exp] = '@exp')", "@exp NVARCHAR(255)", "@exp = 'Risk Management'"

Разница объясняется более подробно в этой статье о Основы подключения к SQL Server.

person Michael Edenfield    schedule 21.08.2013