为查询字符串声明变量

问题描述 投票:78回答:4

我想知道在MS SQL Server 2005中是否有办法做到这一点:

  DECLARE @theDate varchar(60)
  SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

  SELECT    AdministratorCode, 
            SUM(Total) as theTotal, 
            SUM(WOD.Quantity) as theQty, 
            AVG(Total) as avgTotal, 
            (SELECT SUM(tblWOD.Amount)
                FROM tblWOD
                JOIN tblWO on tblWOD.OrderID = tblWO.ID
                WHERE tblWO.Approved = '1' 
                AND tblWO.AdministratorCode = tblWO.AdministratorCode
                AND tblWO.OrderDate BETWEEN @theDate
            )
 ... etc

这可能吗?

sql sql-server sql-server-2005 tsql dynamic-sql
4个回答
81
投票

这是可能的,但它需要使用动态SQL。 我建议在继续之前阅读The curse and blessings of dynamic SQL ...

DECLARE @theDate varchar(60)
SET @theDate = '''2010-01-01'' AND ''2010-08-31 23:59:59'''

DECLARE @SQL VARCHAR(MAX)  
SET @SQL = 'SELECT AdministratorCode, 
                   SUM(Total) as theTotal, 
                   SUM(WOD.Quantity) as theQty, 
                   AVG(Total) as avgTotal, 
                  (SELECT SUM(tblWOD.Amount)
                     FROM tblWOD
                     JOIN tblWO on tblWOD.OrderID = tblWO.ID
                    WHERE tblWO.Approved = ''1''
                      AND tblWO.AdministratorCode = tblWO.AdministratorCode
                      AND tblWO.OrderDate BETWEEN '+ @theDate +')'

EXEC(@SQL)

动态SQL只是一个SQL语句,在执行之前作为字符串组成。因此通常会发生字符串连接。每当您想要在SQL语法中执行不允许的操作时,都需要动态SQL,例如:

  • 单个参数,表示IN子句的逗号分隔值列表
  • 一个表示值和SQL语法的变量(IE:您提供的示例)

EXEC sp_executesql允许您使用bind / preparedstatement参数,因此您不必担心SQL注入攻击转义单引号/ etc。


49
投票
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

然后更改您的查询以使用此逻辑:

AND 
(
    tblWO.OrderDate > DATEADD(MILLISECOND, -1, @theDate) 
    AND tblWO.OrderDate < DATEADD(DAY, 1, @theDate)
)

2
投票

Using EXEC

您可以使用以下示例来构建SQL语句。

DECLARE @sqlCommand varchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = '''London'''
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = ' + @city
EXEC (@sqlCommand)

Using sp_executesql

使用此方法,您可以确保传递给查询的数据值是正确的数据类型,并避免使用更多引号。

DECLARE @sqlCommand nvarchar(1000)
DECLARE @columnList varchar(75)
DECLARE @city varchar(75)
SET @columnList = 'CustomerID, ContactName, City'
SET @city = 'London'
SET @sqlCommand = 'SELECT ' + @columnList + ' FROM customers WHERE City = @city'
EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city

Reference


1
投票

我将指出,在最受好评的答案The Curse and Blessings of Dynamic SQL链接的文章中,作者声明答案不是使用动态SQL。滚动几乎到最后看到这个。

从文章:“正确的方法是将列表解压缩到具有用户定义的函数或存储过程的表中。”

当然,一旦列表在表中,您就可以使用连接。我无法直接评论最高评分的答案,所以我刚添加了这条评论。

© www.soinside.com 2019 - 2024. All rights reserved.