We have relaunched: What's new at ZDNet Asia?

Generate dynamic SQL statements in SQL Server

Summary

Learn to generate on the fly SQL statements, which can be used to solve tricky database problems.

Events

Microsoft MSDN/Developer Event
25 Mar 2010

One Marina Boulevard, Microsoft Singapore

IT Architect Regional Conference Singapore 2010
20 - 21 Apr 2010

Singapore Management University, Singapore

The Internet Show 2010
21-22 Apr 2010

Suntec Singapore

When you need to solve a tricky database problem, the ability to generate SQL statements is a powerful tool--although you must be careful when using it. This article explores how you can use this functionality to generate SQL statements on the fly.

Dynamic SQL statements
A dynamic SQL statement is constructed at execution time, for which different conditions generate different SQL statements.

It can be useful to construct these statements dynamically when you need to decide at run time what fields to bring back from SELECT statements; the different criteria for your queries; and perhaps different tables to query based on different conditions.

These SQL strings are not parsed for errors because they are generated at execution time, and they may introduce security vulnerabilities into your database. Also, SQL strings can be a nightmare to debug, which is why I have never been a big fan of dynamically built SQL statements; however, sometimes they are perfect for certain scenarios.

A dynamic example
The question I answer most often is, "How can I pass my WHERE statement into a stored procedure?" I usually see scenarios similar to the following, which is not valid TSQL syntax:

DECLARE @WhereClause NVARCHAR(2000)
 SET @WhereClause = ' Prouct = ''Computer'''     

 SELECT * FROM SalesHistory WHERE @WhereClause

In a perfect world, it would make much more sense to do the following:

DECLARE @Product VARCHAR(20)
 SET @Product = 'Computer'     

 SELECT * FROM SalesHistory WHERE Product = @Product

It isn't always this easy. In some scenarios, additional criteria is needed, and as tables grow wider, more and more criteria is often needed. This can typically be solved by writing different stored procedures for the different criteria, but sometimes the criteria is so different for each execution that covering all of the possibilities in a stored procedure is burdensome. While these stored procedures can be made to take into account every WHERE statement possible depending on different parameters, this often leads to a degradation in query performance because of so many conditions in the WHERE clause.

Let's take a look at how to build a simple dynamic query. First, I need a table and some data to query. The script below creates my SalesHistory table and loads data into it:

CREATE TABLE [dbo].[SalesHistory]
  (        
        [SaleID] [int] IDENTITY(1,1),        
        [Product] [varchar](10) NULL,              
        [SaleDate] [datetime] NULL,               
        [SalePrice] [money] NULL
  )
  GO              

  SET NOCOUNT ON             

  DECLARE @i INT
  SET @i = 1          
  WHILE (@i <=5000)
  BEGIN                                       

         INSERT INTO [SalesHistory](Product, SaleDate, SalePrice)                    
         VALUES ('Computer', DATEADD(ww, @i, '3/11/1919'),
         DATEPART(ms, GETDATE()) + (@i + 57))                              

         INSERT INTO [SalesHistory](Product, SaleDate, SalePrice)        
         VALUES('BigScreen', DATEADD(ww, @i, '3/11/1927'),
         DATEPART(ms, GETDATE()) + (@i + 13))                                   

         INSERT INTO [SalesHistory](Product, SaleDate, SalePrice)            
         VALUES('PoolTable', DATEADD(ww, @i, '3/11/1908'),
         DATEPART(ms, GETDATE()) + (@i + 29))                                          

       SET @i = @i + 1             

  END

Now I will build my stored procedure that accepts a WHERE clause. For the purpose of this example, I will assume that the WHERE clause was built dynamically from the calling client application.

CREATE PROCEDURE usp_GetSalesHistory
 (
         @WhereClause NVARCHAR(2000) = NULL
 )
 AS
 BEGIN
         DECLARE @SelectStatement NVARCHAR(2000)
         DECLARE @FullStatement NVARCHAR(4000)     

         SET @SelectStatement = 'SELECT TOP 5 * FROM SalesHistory '
         SET @FullStatement = @SelectStatement + ISNULL(@WhereClause,'')     

         PRINT @FullStatement
         EXECUTE sp_executesql @FullStatement     

                /*
  --can also execute the same statement using EXECUTE()
         EXECUTE (@FullStatement)      
         */
 END

I set the @WhereClause parameter to allow NULL values because we may not always want to pass a value in for the @WhereClause.

For every execution of this stored procedure, every field is returned for the TOP 5 rows from SalesHistory. If there is a value passed in for the @WhereClause parameter, the executing statement will append that string to the @SelectStatement string. Then I use the stored procedure sp_executesql to execute the dynamically built SQL string.

sp_executesql or EXECUTE()
There are two ways to execute dynamic SQL in SQL Server: use the sp_executesql system stored procedure or the EXECUTE() operator. Sometimes the two methods can produce the same result, but there are differences in how they behave.

The system stored procedure sp_executesql allows for parameters to be passed into and out of the dynamic SQL statement, whereas EXECUTE() does not. Because the SQL statement is passed into the sp_executesql stored procedure as a parameter, it is less suseptible to SQL injection attacks than EXECUTE(). Since sp_executesql is a stored procedure, passing SQL strings to it results in a higher chance that the SQL string will remain cached, which should lead to better performance when the same SQL statement is executed again. In my opinion, sp_executesql results in code that is a lot cleaner and easier to read and maintain. These reasons are why sp_executesql is the preferred way to execute dynamic SQL statements.

In my previous example, I looked at how you can build a simple SQL statement by passing a WHERE clause into a stored procedure. But what if I want to get a list of parameter values from my dynamically built SQL statement? I would have to use sp_executesql because it is the only one of my two options that allows for input and output parameters.

I am going to slightly modify my original stored procedure so that it will assign the total number of records returned from the SQL statement to an output parameter.

DROP PROCEDURE usp_GetSalesHistory
 GO
 CREATE PROCEDURE usp_GetSalesHistory
 (
         @WhereClause NVARCHAR(2000) = NULL,          
         @TotalRowsReturned INT OUTPUT
 )
 AS
 BEGIN
         DECLARE @SelectStatement NVARCHAR(2000)
         DECLARE @FullStatement NVARCHAR(4000)
         DECLARE @ParameterList NVARCHAR(500)     

         SET @ParameterList = '@TotalRowsReturned INT OUTPUT'     

 SET @SelectStatement = 'SELECT @TotalRowsReturned 
 = COUNT(*) FROM SalesHistory '
         SET @FullStatement = @SelectStatement + ISNULL(@WhereClause,'')     

         PRINT @FullStatement
             EXECUTE sp_executesql @FullStatement, @ParameterList, 
             @TotalRowsReturned = @TotalRowsReturned OUTPUT
 END
 GO

In the above procedure, I need to declare a parameter list to pass into the sp_executesql stored procedure because a value is being assigned to the variable at run time. The only other change to the sp_executesql call is that I am assigning the output parameter from the call to the local @TotalRowsReturned parameter in my usp_GetSalesHistory stored procedure.

I can even call my usp_GetSalesHistory stored procedure similar to the way I did before, but with the addition of an output parameter to indicate the rows that were returned.

DECLARE @WhereClause NVARCHAR(2000), @TotalRowsReturned INT
 SET @WhereClause = 'WHERE Product = ''Computer'''     

 EXECUTE usp_GetSalesHistory
 @WhereClause = @WhereClause,
 @TotalRowsReturned = @TotalRowsReturned OUTPUT     

 SELECT @TotalRowsReturned

Caution
Although I am not a huge fan of using dynamic SQL statements, I believe it is a great option to have in your tool belt.

If you decide to incorporate dynamic SQL into your production level code, be careful. The code is not parsed until it is executed, and it can potentially introduce security vulnerabilities that you do not want.

If you are careful with your dynamic SQL statement, it can help you create solutions to some pretty tricky problems.

Tim Chapman a SQL Server database administrator and consultant who works for a bank in Louisville, KY. Tim has more than eight years of IT experience, and he is a Microsoft certified Database Developer and Administrator. If you would like to contact Tim, please e-mail him at chapman.tim@gmail.com.

Talkback

Add your opinion

In order to post a comment, you need to be registered. (Sign In or register below)

Post your comment
Transform your business interactions with real-time voice, video and telepresence solutions.
Tech Vendor: Cisco

ZDNet Asia Live

Found this great little deal calculator http://www.zdnetasia.com/downloa...

3 hours 18 minutes ago by winstoncranford on topsy

RT @mistertechblog: I wrote about Nexus One and Touchdown, desktop dock, Bluetooth/USB tethering, ebooks here: http://bit.ly/bRdzx0

9 hours 30 minutes ago by yklee13 on topsy

Read my blog post on getting the most from your Nexus One: http://www.zdnetasia.com/blogs/m...

Data Centre Operator (Fresh Graduates Welcome to Apply) in ... http://bit.ly/bagYuu

10 hours 36028 seconds ago by intmasterfeed on topsy

#Cisco #Cloud Cloud on ZDNet Asia: Aussie university joins Cisco cloud ยท Early-adopter criminals embrace cloud... http://bit.ly/d93C8S #TCN

11 hours 3 minutes ago by thetechgang on topsy

www.3w.com.au has seen it's outsourced IT Contracting Business in Manila grow at 4 times the rate of its traditional Australian Based...

17 hours 41 minutes ago by brucemills on Companies' outsourcing spend to increase

RT @3wconsulting: Whitepaper from http://3W.com.au "Outsourcing Your IT Requirements to Philippines" now on @zdnetaustralia & @zdnetasia http://ow.ly/1oY9f

Whitepaper from http://3W.com.au "Outsourcing Your IT Requirements to Philippines" now on @zdnetaustralia & @zdnetasia http://ow.ly/1oYbA

Whitepaper from http://3W.com.au "Outsourcing Your IT Requirements to Philippines" now on @zdnetaustralia & @zdnetasia http://ow.ly/1oYbz

Zdnetasia.com Estimated Worth $178,365 USD. Daily Ad Revenue:$244 USD, Daily Views:81,445 Pages... - http://www.haplog.com/www.zdneta...

When I create an event, I click on an approximate time during the day when I want the event to occur, then I click "edit event detail...

1 day 10 minutes ago by bessellbrowne on Google Calendar gets 'smart' rescheduling

ipads break alott i had one it broke three times in the month i had it so i got rid of the damn thing id just go for the laptop Top Grade...

1 day 12 minutes ago by bessellbrowne on Report: 'Hundreds of thousands' of iPad preorders

There are a number of websites that still require Internet Explorer to view and IE for Mac Stinks (it is really ies4osx which is the Wind...

1 day 13 minutes ago by bessellbrowne on Microsoft: Only minor tweaks in Windows 7 SP1

The receivers don't transmit back to the satellite. Unless there is a phone line attached to the receiver, they don't have any wa...

1 day 16 minutes ago by bessellbrowne on Apple to join the geolocation craze?

"Lead Cognos BI Developer Insurance - Jobs - ZDNet Asia" http://bit.ly/bRcxOG

1 day 11 minutes ago by rhrcognos on topsy

whatever little understanding I have we 'll only progress toward end of the world if we use HPCs to lenthen life of human being. Huma...

2 days 23 minutes ago by abhi32002@gmail.com on High computing promises elixir of life

Thanks for the knowledgeable article on SDDs. Allas...when all this reasearch will happen in Indian Universities. Hope the new bill on Fo...

2 days 35 minutes ago by abhi32002@gmail.com on APAC HPC users eye solid-state drives

It was a good article. This brings a good opportunity for Indian IT firms to come up with new solutions in this field. HPC can become a b...

2 days 54 minutes ago by abhi32002@gmail.com on High computing most-wanted job in Asia

COL KR DHARMADHIKARY(RETD) its very late to reply the link, but if it is still alive and looking for opportunity, i would like to know th...

2 days 51 minutes ago by deb021280 on Education takes off in rural India, helped by PCs

It was just a matter of time until google was marginalised anyway. I'm afraid this will be forgotten in China very quickly. Still, it...

2 days 56 minutes ago by robinsmith on Report: Google to leave China on April 10

High performance computing (HPC) most-wanted job in Asia http://bit.ly/9vFC3i (via @zdnetasia) #singapore

He doesn't care if her shoes are of glass, All he wants to see is a huge rack and nice a*s. Sleeping beauty's not awoken by true ...

2 days 25 minutes ago by warlowdavies on One pair of 3D glasses to rule them all

RT @zdnetasia: EMC COO, Pat Gelsinger, on bridging gaps in the organization and its cloud ambitions in Asia. (cont) http://tl.gd/i5jjd

EMC COO, Pat Gelsinger, on bridging gaps in the organization and its cloud ambitions in Asia. http://bit.ly/9etOZW

Asian SMBs need to pay more attention to disaster recovery planning http://bit.ly/bDet08 via @zdnetasia

Asian SMBs need to pay more attention to disaster recovery planning http://bit.ly/bDet08

[TECH] URL Shorteners slow Web redirection. - http://bit.ly/bySnWK @zdnetasia

URL shorteners are great but they can slow web redirection & you pray it would never go down http://bit.ly/bySnWK via @zdnetasia

URL shorteners slow Web redirection. http://bit.ly/bySnWK

Chinese agencies cry foul over Google. http://bit.ly/by6rwV

all of sg's isps have been practising compulsory invisible proxy for all home subscribers at their backend since many years back alre...

3 days 35 minutes ago by melvinchia on Web filters mean bad news for business

it is not to good for china.
Proactol

3 days 20 minutes ago by nathonastle on Chinese ad partners beg Google for information

Very good explanation of JMX

4 days 25 minutes ago by Babith B on Managing applications with JMX

The reaction to a report issued Tuesday by Flurry Analytics managed to completely overlook some interesting news--the Android-based Motorola Droid outsold the original iPhone over the same period of time following their respective launches--to focus instead on the sales numbers for the Nexus One.

4 days 29 minutes ago by lonemavericks on diggs

Another ZTE story....

4 days 30 minutes ago by Moderate Your Greed on Philippines opens bid for final 3G license