Declare Variable for a Query String

SqlSql ServerSql Server-2005TsqlDynamic Sql

Sql Problem Overview


I was wondering if there was a way to do this in 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

Is this possible to do?

Sql Solutions


Solution 1 - Sql

It's possible, but it requires using dynamic SQL.
I recommend reading The curse and blessings of dynamic SQL before continuing...

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)

Dynamic SQL is just a SQL statement, composed as a string before being executed. So the usual string concatenation occurs. Dynamic SQL is required whenever you want to do something in SQL syntax that isn't allowed, like:

  • a single parameter to represent comma separated list of values for an IN clause
  • a variable to represent both value and SQL syntax (IE: the example you provided)

EXEC sp_executesql allows you to use bind/preparedstatement parameters so you don't have to concern yourself with escaping single quotes/etc for SQL injection attacks.

Solution 2 - Sql

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

Then change your query to use this logic:

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

Solution 3 - Sql

Using EXEC

You can use following example for building SQL statement.

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

With using this approach you can ensure that the data values being passed into the query are the correct datatypes and avoind use of more quotes.

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

Solution 4 - Sql

I will point out that in the article linked in the top rated answer The Curse and Blessings of Dynamic SQL the author states that the answer is not to use dynamic SQL. Scroll almost to the end to see this.

From the article: "The correct method is to unpack the list into a table with a user-defined function or a stored procedure."

Of course, once the list is in a table you can use a join. I could not comment directly on the top rated answer, so I just added this comment.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionStealthRTView Question on Stackoverflow
Solution 1 - SqlOMG PoniesView Answer on Stackoverflow
Solution 2 - SqlhunterView Answer on Stackoverflow
Solution 3 - SqlSomnath MulukView Answer on Stackoverflow
Solution 4 - SqlDavidGView Answer on Stackoverflow