声明查询字符串的变量


92

我想知道在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

这可能吗?


Answers:


96

可能,但是需要使用动态SQL。
我建议在继续之前阅读动态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。


我认为这是最正确的答案。我最近也一直在使用SQL Server 2005,并且无法使用OP想要的变量来替换查询字符串(生成语法错误)。正如@Ponies所说,变量不能同时包含语法和数据类型。动态SQL是通过字符串在SQL Server中构建查询的一种方式。只要记住要小心您的引号和类型!您执行的字符串需要某些类型(例如datetime或int)进行转换或强制转换以进行字符串连接。
RoboBear 2015年

52
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

然后更改查询以使用以下逻辑:

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

2
不挂断。如果问题清楚地显示了两个不同的日期,那将不是答案。您如何在@StealthRT最后编写代码?答案中的“ 2010-08-31”日期在哪里?另外,该问题清楚地询问您是否可以使用DECLARE变量将代码替换为另一个SELECT语句。正确的答案如下。
Fandango68年

2

使用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)

使用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

参考


1

我将指出,在评价最高的答案中链接的文章《动态SQL诅咒与祝福》中,作者指出,答案不是使用动态SQL。滚动到最后将其看到。

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

当然,一旦列表在表中,您就可以使用联接。我无法直接对评分最高的答案发表评论,所以我只添加了此评论。


这不能为问题提供答案。一旦您拥有足够的声誉,您就可以在任何帖子中发表评论;而是提供不需要问询者澄清的答案。- 来自评论
Sam M

谢谢山姆。一旦实施Erland Sommarskog的建议,我将详细更新评论。我还将按名字提及他,因为他的答案值得称赞。
DavidG '18年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.