【问题标题】:When parameterized query executes it does not seem to have a value for the parameter当参数化查询执行时,它似乎没有参数的值
【发布时间】:2013-08-22 13:00:54
【问题描述】:

据我了解,以下代码应该创建一个参数化语句并向该参数添加一个值。参数为“@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"]);
}

我确定这是我缺少的一些简单的东西,但我无法看到它。

【问题讨论】:

  • 您的期望是错误的 - 使用参数并不意味着客户端 SQL 代码会将这些参数替换为它们的实际值。参数作为参数发送到 SQL Server,包括它们的值在值列表中。这就是它的设计方式和设计方式 - 如果您希望在将查询发送到 SQL Server 之前将参数替换为其实际值,那您就错了。

标签: c# parameterized-query


【解决方案1】:

您在这里处理的是变量,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 中,即使添加了参数,这实际上是正确的。

【讨论】:

    【解决方案2】:

    当您通过 .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 Connection Basics.的这篇文章更详细地解释了区别

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-02
      • 2020-05-23
      相关资源
      最近更新 更多