Объявить переменную для строки запроса - PullRequest
80 голосов
/ 30 сентября 2010

Мне было интересно, есть ли способ сделать это в 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

Возможно ли это сделать?

Ответы [ 4 ]

83 голосов
/ 30 сентября 2010

Это возможно, но требует использования динамического 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 позволяет использовать параметры связывания / подготовленного состояния, поэтому вам не нужно заботиться о экранировании одинарных кавычек/ etc для атак с использованием SQL-инъекций.

49 голосов
/ 30 сентября 2010
DECLARE @theDate DATETIME
SET @theDate = '2010-01-01'

Затем измените ваш запрос, чтобы использовать эту логику:

AND 
(
    tblWO.OrderDate > DATEADD(MILLISECOND, -1, @theDate) 
    AND tblWO.OrderDate < DATEADD(DAY, 1, @theDate)
)
2 голосов
/ 22 сентября 2017

Использование 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

1012 * Ссылка *

1 голос
/ 05 января 2018

Я укажу, что в статье, указанной в ответе с самым высоким рейтингом Проклятие и благословения динамического SQL , автор утверждает, что ответ не должен использовать динамический SQL. Прокрутите почти до конца, чтобы увидеть это.

Из статьи: «Правильный метод - распаковать список в таблицу с пользовательской функцией или хранимой процедурой.»

Конечно, когда список находится в таблице, вы можете использовать объединение. Я не мог прокомментировать непосредственно ответ с самым высоким рейтингом, поэтому я просто добавил этот комментарий.

...