【问题标题】:Parametrize query in t-sqlt-sql 中的参数化查询
【发布时间】:2014-07-22 13:45:30
【问题描述】:
SELECT TOP @columnCount @columnName 
FROM @tableName

我收到以下错误

“@columnCount”附近的语法不正确。

可能出了什么问题?

如果我改成

SELECT TOP (@columnCount) @columnName 
FROM @tableName

我收到以下错误

必须声明表变量“@tableName”。

我从 C# 运行它

【问题讨论】:

  • 将字段名称作为参数传递没有多大意义 - 参数化查询是关于重用执行计划。更改字段可以完全改变最佳执行计划。您可以使用 SQL Server 2008 R2+ 中的TOP(@someParam)

标签: sql sql-server tsql sql-parametrized-query


【解决方案1】:

一种安全可靠的方式是

DECLARE @columnCount INT = 100
DECLARE @columnName  NVARCHAR(128) = 'YourColumnName'
DECLARE @tableName   NVARCHAR(128) = 'YourTableName'

DECLARE @Sql NVARCHAR(MAX);

SET @Sql = N'SELECT TOP (@columnCount) ' +  QUOTENAME(@columnName) + N' 
            FROM ' + QUOTENAME(@tableName)

EXECUTE sp_executesql @Sql
                     ,N'@columnCount INT'
                     ,@columnCount

【讨论】:

    【解决方案2】:

    您需要动态 SQL 来完成您想要做的事情。

    DECLARE @sql VARCHAR(max);
    SET @sql = 'SELECT TOP ' + @columnCount + ' ' + @columnName + ' FROM ' + @tableName;
    EXEC(@sql);
    

    使用的变量需要进行适当的转换。

    documentation了解更多信息

    【讨论】:

    • 这不会引发错误,因为@ColumnCount 变量很可能是Int 变量:) 并且此代码易受 SQL 注入攻击。
    • @M.Ali "使用的变量需要适当转换。"
    【解决方案3】:

    列列表和表名不能是参数。但是,由于您是从 C# 运行它,因此从技术上讲,您已经在使用动态 SQL(除非您使用这些参数调用存储过程,但这里没有提到使用存储过程,所以现在我假设不会)。在 C# 中构建 SQL 时,您需要将列列表和表名称连接到查询中,但您仍然可以为 TOP() 运算符使用的值使用参数:

    SqlConnection _Connection = new SqlConnection("connection string");
    SqlCommand _Command = new SqlCommand();
    SqlDataReader _Reader = null;
    
    string _Query;
    string _TableName = "dbo.MyTable";
    string _ColumnList = "Field1, Field2 AS [AliasedName], Field3";
    int _NumberOfRows = 12;
    
    _Query = String.Concat("SELECT TOP (@NumberOfRows) ",
        _ColumnList, " FROM ", _TableName);
    
    SqlParameter _NumRows = new SqlParameter("@NumberOfRows", SqlDbType.Int);
    _NumRows.Value = _NumberOfRows;
    
    try
    {
        _Connection.Open();
        _Reader = _Command.ExecuteReader();
        // do stuff
    }
    finally
    {
        _Reader.Close();
        _Connection.Close();
    }
    

    当然,您也可以直接将 @NumberOfRows 值连接到查询中,但是如果使用相同的 ColumnList 和 TableName 值多次运行此查询,将其作为参数保留将允许查询计划重用但更改 @NumberOfRows 值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-04
      • 2012-06-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多