我理解的下面的代码应该创建一个参数化语句并为该参数添加一个值。参数为“@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]的值一样。这是对的吗?
我已经看到了多种方法,但我一般都遵循示例here
我不认为这是问题,但这就是我使用查询的方式。
SQl_Reader = SQl_Command.ExecuteReader();
int numRows = 0;
while(SQl_Reader.Read()){
numRows = Convert.ToInt32(SQl_Reader["MyCount"]);
}
我确信这是一件很简单的事情,但我却无法看到它。
答案 0 :(得分:6)
您在这里处理变量,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
中,这实际上是正确的。
答案 1 :(得分:1)
当您通过其中一个.NET SQL Server提供程序运行参数化查询时,查询会将其保持参数化形式一直到服务器。如果您在执行查询时运行SQL事件探查器,则会看到发生执行查询的“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'"
的详细解释