Call now: (800) 766-1884  


 SQL Server Tips
 SQL Server Training

 SQL Server Consulting
 SQL Server Support
 SQL Server Remote DBA

 SQL Server Scripts
 Scripts Menu




  SQL Server Tips by Gama and Naughter


Dynamic SQL

Dynamic SQL is SQL code executed from within a statement and changed according to the logic of the code that created it. Basically, TSQL code will create a string with other TSQL code and execute it. A query that returns a variable number of columns sounds unnatural but there are real world situations that need it.


Advantages of dynamic SQL

  • Reuse code for different tables or other objects.

  • Reuse code for different databases.

  • Use variable names in statements that require constants.

  • Avoid statements that would be either impossible or very hard to code because of the high number of possibilities involved.

  • Return rowsets with a variable number of columns and/or variable column names.

  • Allow parameterized filtering with the IN clause.

  • Sorting by any column from a table.

Disadvantages of dynamic SQL

  • Performance loss: the execution plan for a dynamic query cannot be cached.

  • Hard to debug.

  • The error management becomes more unreliable. There is no easy way to validate the dynamic code or control its effects.

  • Temporary tables from the main statement cannot be used, unless they are global.

  • If the algorithm of the main statement has many loops, calculations or slow queries, that time will add up to the time of executing the dynamic code.

  • Maintenance is difficult because the schema is hard coded in the dynamic code. The main statement is harder to understand than regular code because it is necessary to consider how it affects the dynamic code, without seeing it.

  • Security can be compromised with SQL injection.


Reuse code for different objects

If the same code is used very often for different objects and the only change is the objectís name then using dynamic SQL will certainly allow for consolidating this code in one object only.


Example: Create an SP that will return the mean from a selected column from a table. The column and table names are the input parameters.


CREATE PROCEDURE myDynamicMean (@Column NVARCHAR(128), @Table NVARCHAR(128))

--Calculates the mean of any column from any table dynamically



SET @SQL='SELECT AVG('+@Column+'*1.0) AS Mean FROM '+@Table



The dynamic code has the usual code to return the mean value of a column from a table but both table and column names are variable.


Example: Create an SP that will return the mode from a selected column from a table. The column and table names are the input parameters.


CREATE PROCEDURE myDynamicMode (@Column NVARCHAR(128), @Table NVARCHAR(128))

--Calculates the modal of any column from any table dynamically



SET @SQL='SELECT '+@Column+' AS Mode FROM '+@Table+' GROUP BY '+@Column+' HAVING COUNT(*) =

(SELECT MAX(tcount) as Tmax FROM (SELECT COUNT(*) as tcount  FROM  '+@Table+'  GROUP BY '+@Column+') tmpCount)'



In this example there are more changes to be performed to the dynamic code because the parameters are to replace more sections of the dynamic code than in the previous example. It is still an exercise of substitution.


Reuse code for different databases

An interesting advantage of using dynamic SQL is that it provides access to any database because the dynamic code can append the database name before an objectís name. The previous examples can be called with the database name specified and the SP will get the table data from the corresponding databases:


There are two main reasons to use the same code amongst different databases, the first one is that the code might do some maintenance or administrative tasks; the second is that different versions of the same database are kept because either some versions contain historic data or each version should be independent from the rest. Keeping the code in one place allows easier maintenance, although not better performance.


Example: Create an SP that will list all the user tables from a database.

The input is the database name.



--lists all the user tables for the selected database



FROM  '+@db+'..sysobjects

WHERE (type = ''u'') AND (name <> N''dtproperties'')')


In this example the database name is the input while in the previous example the table name had the database name attached. If the SP joins the table name from the input with another table the effect could be an heterogeneous query. If this is not the desired effect, it will probably result in an error.


Example: Create an SP that will list all the user table names from two databases, which have similar names.



--lists all the user tables with similar names from the current database and the selected database


EXEC('SELECT, AS ['+@db+']


                ['+@db+']..sysobjects s2 ON SOUNDEX( = SOUNDEX(

WHERE (sysobjects.type = ''u'') AND (s2.type = ''u'') AND ( <> N''dtproperties'') AND ( <> N''dtproperties'')')


It is also useful to access tables or views from linked servers and even different instances from a linked server. To use an SP with a table from a linked server the server name must precede the table name, for example:

EXEC CompareTables ĎmyLinkedServer.northwindí

And an instance in that server:


EXEC CompareTables Ď[myLinkedServer\instance1].northwindí


Use variable names in statements that require constants

There are several TSQL statements that will generate an error message when trying to use a variable for its input. The most obvious case is the SELECT statement with the TOP clause. The TOP clause requires a constant while variables can be used as column values, as part of WHERE filter expressions or in CASE clauses.


Example: Create a SP that will return the top n rows from a table or view with n being the SPís input.


CREATE PROCEDURE myDynamicTopN (@Top int, @Table NVARCHAR(128))

--Retuns the top N rows from any table dynamically






There is another way to obtain the same result; it is the SET ROWCOUNT statement. It causes the query being executed to perform changes to the first n rows with n defined by the SET ROWCOUNT statement. This statement affects not only SELECT but also DELETE, INSERT and UPDATE. This is an example of using such method:


CREATE PROCEDURE myDynamicTopN2 (@Top int, @Table NVARCHAR(128))

--Retuns the top N rows from any table dynamically







This method is not recommended and TOP should be used instead because of performance issues.


Example: Create a SP that will kill the process allocated to a user connection by the user name. For simplicity, let us assume that the user will take only one process.


CREATE PROCEDURE KillUserProcess @user nvarchar(128)


--Kills one process from a certain user, assuming only one process is active

DECLARE @spid int

SELECT @spid=spid

      FROM  master.dbo.sysprocesses

WHERE rtrim(loginame)=@user

EXEC ('KILL '+ @spid)


The first part of the code will get the process id taken by the user, by querying sysprocesses. The KILL statement is one of those statements that require a constant as input.


Avoid statements with an extremely high number of possibilities

The crosstab SPís are the best examples where the input allows for a complex query to be created dynamically that would be impossible to hardcode. One example is when a decision is made based on a number, if the number is not within a very small range, then the logic tree could grow beyond practical limits. A decision based on names of people or cities would have the same problem.


Return rowsets with a variable number of columns

When creating queries for reports, sometimes the specifications ask for plenty of flexibility. Queries must always return a fixed number of columns and dynamic SQL is one way to work around that.


Example: Create a SP that will return the N first columns from a table. The input will be the table name and the number of columns to be returned.


CREATE PROCEDURE spTableNfirstColumns @table  NVARCHAR(128), @Ncols int

--returns the N first columns from a table



SET @ColNames=''



SET @ColNames=RIGHT(@ColNames, LEN(@ColNames)-1)

SET @SQL=N'SELECT '+@ColNames+N' FROM '+@table



Example: Create a SP that will return the product names from table Categories and a variable number of columns, each one corresponding to a category. Under each category column, there would be the number of products in stock.


CREATE PROCEDURE spProductsByCategory

--returns the product names and their number in stock, with the number under a category column



SET @SQL='SELECT Products.ProductName, '

DECLARE @CategoryID int, @CategoryName NVARCHAR(15)


FOR SELECT CategoryID, CategoryName FROM  Categories

OPEN cur_ds

FETCH NEXT FROM cur_ds INTO @CategoryID, @CategoryName



      SET @SQL=@SQL+'CASE Products.categoryid WHEN '+CAST(@CategoryID as CHAR)

      +' THEN Products.UnitsInStock ELSE 0 END AS ['+CAST(@CategoryName as CHAR)+'],'

      FETCH NEXT FROM cur_ds INTO @CategoryID, @CategoryName


CLOSE cur_ds


SET @SQL=LEFT(@SQL,LEN(@SQL)-1)--remove the last comma

SET @SQL=@SQL+'FROM  Products INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID'



Allow parameterized filtering with the IN clause

Example: Create a SP that will return rows from table Shippers filtering by ShipperID. Any combination of ShipperID should be possible by means of using the IN clause with its filter data as an input parameter of the SP.


CREATE PROCEDURE spOrdersByShipperID @Shippers varchar(20)

--returns the orders by any combination of shipper ID's


EXEC('SELECT dbo.Orders.OrderID, dbo.Orders.ShipName, dbo.Orders.ShipCity, dbo.Orders.ShipRegion, dbo.Orders.ShipPostalCode, dbo.Orders.ShipCountry,



               dbo.Shippers ON dbo.Orders.ShipVia = dbo.Shippers.ShipperID

WHERE (dbo.Shippers.ShipperID IN ('+@Shippers+'))')

The above book excerpt is from:

Super SQL Server Systems
Turbocharge Database Performance with C++ External Procedures

ISBN: 0-9761573-2-2
Joseph Gama, P. J. Naughter


Burleson Consulting Remote DB Administration







Burleson is the America's Team

Note: The pages on this site were created as a support and training reference for use by our staff of DBA consultants.  If you find it confusing, please exit this page.

Errata?  SQL Server technology is changing and we strive to update our SQL Server support information.  If you find an error or have a suggestion for improving our content, we would appreciate your feedback.  Just  e-mail:and include the URL for the page.

Burleson Consulting
SQL Server database support


Copyright © 1996 -  2013 by Vaaltech Web Services. All rights reserved.

Hit Counter