【问题标题】:SQL Table as parameter with IDBCommandSQL 表作为 IDBCommand 的参数
【发布时间】:2013-08-18 19:28:06
【问题描述】:

我正在试验如何让 Web 应用程序支持多个数据库,特别是 SQL Server 和 MySQL。

我已经设置了我的 SQL 帮助程序类,它将负责连接到数据库和查询执行。我正在使用IDBCommandIDBConnection 等。我已经用控制台应用程序测试了这个类,它可以很好地处理不带参数的查询。

但是当我添加参数时,问题就出现了。

我希望为表名使用参数,因为当前表名可能会更改,并且在查询中重命名表会很痛苦。

我找到了一篇文章,其中作者分享了他向IDBCommand 添加参数的方法。我找不到文章的链接,但这是我从文章中得到的示例(感谢作者顺便说一句!:D)我能够确认参数已添加,因为它们列在 @987654324 下@ 使用 QuickWatch,但我得到一个“必须声明表变量“@myTable”。”错误。

    internal static int AddInputParameter<T>(this IDbCommand cmd,
    string name, T value)
    {
        var p = cmd.CreateParameter();
        p.ParameterName = name;
        p.Value = value;
        return cmd.Parameters.Add(p);
    }

知道我做错了什么吗?

编辑:
为了回应 bew 的回复,我可以同时使用 SqlCommandMySqlCommand

编辑2:
看来我记错了。我在过去的项目中使用string.format() 作为表名。

【问题讨论】:

  • 我不确定在 Visual Studio 2010 中是否允许通过参数填充表,在我的情况下,我使用了变量
  • 我可以使用 SqlCommand 做到这一点。
  • 你在签名中返回int,什么时候这个方法会在return语句中返回SqlParameter
  • 我猜它就像添加 @ 一样简单。

标签: c# asp.net mysql sql sql-server


【解决方案1】:

简短的回答是您不能将表格作为参数传递。相反,您要在运行时确定表的任何查询都必须先组装为字符串,然后才能用于参数化查询。更长的答案需要了解当您使用参数化动态 SQL 语句调用 cmd.ExecuteReader 之类的内容时会发生什么。在这种情况下,.NET 类使用sp_executesql 构建调用。例如:

Declare @Sql nvarchar(max);
Set @Sql = 'Select Count(*) From sys.objects Where object_id > @SomeNum';
exec sp_executesql @Sql, N'@SomeNum int', 10000;

现在假设我们尝试将表的参数插入到 SQL 语句中。结果语句将是:

Declare @Sql nvarchar(max);
Set @Sql = 'Select Count(*) From @SomeTable Where object_id > @SomeNum';
exec sp_executesql @Sql, N'@SomeTable nvarchar(256),@SomeNum int', 'sys.objects', 10000;

这将导致类似于Must declare the table variable "@SomeTable" 的错误。 SQL Server 不知道@SomeTable 是一个参数,而不是一个表变量。因此,对象引用(表、视图、过程等)不是您可以参数化的东西;只有标准可以参数化。

【讨论】:

  • 虽然这是特定于 sql server 的问题,而且问题明确地涉及支持的不仅仅是 sql server,但答案的要点是正确的:您不能将表名作为参数传递。对为什么大多数 RDBM 处理查询的更好解释是首先编译它(在某个级别)以产生某种执行计划。此步骤还将涉及验证连接的用户是否具有适当的权限……如果它不知道硬表名称,则无法确定。此外,如果它不知道硬表名,它就无法知道哪些索引可用于计划。
  • @JoelCoehoorn - 虽然编译问题不是 when 它编译的一个因素吗?即,如果它组装了包含参数值使用的完整 SQL 语句然后编译,它不会遇到问题。在 sp_executesql 的情况下,它正在编译参数化语句,因此会遇到您提到的问题。在 SQL Server 的情况下,我无法想象它会如何以除了它已经执行的顺序之外的任何顺序进行编译。
【解决方案2】:

我不知道这是否会有所帮助,但这是我不久前使用的一个功能。它使用匿名类型来添加参数。随意将其用作模板:

private static void Addparms(SqlCommand cmd, object parms)
{
  // parameter objects take the form new { propname = "value", ... } 
  foreach (PropertyInfo prop in parms.GetType().GetProperties())
  {
    cmd.Parameters.AddWithValue("@" + prop.Name, prop.GetValue(parms, null));
  }
}

然后这样调用:

Addparms(cmdObject, new { name = "Hogan", page = 1, last = "Long" });

这将添加 3 个参数 @name@page@last

【讨论】:

    猜你喜欢
    • 2014-02-01
    • 1970-01-01
    • 2012-01-04
    • 2013-01-23
    • 2011-06-03
    • 1970-01-01
    • 2013-04-02
    • 2023-03-21
    • 1970-01-01
    相关资源
    最近更新 更多