1. What Is Dynamic SQL?
Electronic supplementary material
The online version of this chapter (doi: 10.1007/978-1-4842-1811-2_1 ) contains supplementary material, which is available to authorized users.
TSQL is a scripting language that expands with each new release of SQL Server. Success in the world of database development and administration requires flexibility and the ability to adapt constantly to new situations, technologies, and demands. Many of the challenges youll face are unknowns, or situations where you dont know exactly what kind of data you will be working with until runtime. Dynamic SQL is one of the best tools for solving problems in the face of unknowns.
Understanding Dynamic SQL
Dynamic SQL is quite simple to understand, and once youre acquainted with it, the number of applications you can use it for can become staggering. Dynamic SQL seeks to solve scenarios where you want to operate on one or many objects, but do not know all of the pertinent details as you write the code. Parameters can be passed into the code in order to persist sets of important values, but what do you do when the structure of the TSQL is defined by these values?
A Simple Example
Starting with a very simple select statement , we will build a starting point for understanding Dynamic SQL:
SELECT TOP 10 * FROM Person.Person;
This statement returns all columns of data for 10 rows in the table Person.Person . What if you wanted to select data from a table, but did not know the name of the table until runtime? How would you substitute the variable table name into the TSQL? Before answering that question, lets introduce Dynamic SQL by simply rewriting the above query so that you are executing it as a character string, rather than as standard TSQL:
DECLARE @sql_command NVARCHAR(MAX);
SELECT @sql_command = 'SELECT TOP 10 * FROM Person.Person';
EXEC (@sql_command);
This example defines a character string called @sql_command that will be used to hold the Dynamic SQL. What is the Dynamic SQL? Its the string that you are building and then later executing. In this case, it is the same SELECT statement from above, with no alterations. After you set the @sql_command , it is then executed, providing the same results as above.
The EXEC Statement
EXEC is used to execute @sql_command . EXECUTE may also be used. Other ways to execute Dynamic SQL will be presented later in this book, in response to the need for further flexibility or security. Remember to always put parentheses around the @sql_command string. Heres an example that omits the parentheses:
DECLARE @sql_command NVARCHAR(MAX);
SELECT @sql_command = 'SELECT TOP 10 * FROM Person.Person';
EXEC @sql_command;
Failure to do so will result in a somewhat odd error:
Msg 2812, Level 16, State 62, Line 11
Could not find stored procedure 'SELECT TOP 10 * FROM Person.Person'.
The Dynamic SQL command string is treated by SQL Server as a stored procedure when there are no parentheses. Leave them out and youll be unable to run your SQL string, receiving an error similar to the one above.
Data Types to Use
Note that NVARCHAR(MAX) is used as the data type for the command string. While you could use VARCHAR , you would potentially be losing data if any extended Unicode characters were in any of the objects you work with. The size could also be shortened, but if your command string becomes larger than that size, it will be truncated and your Dynamic SQL will become the source of confusing error messages or logical errors.
For consistency and reliability, use NVARCHAR(MAX) as the data type for your Dynamic SQL command strings.
Dynamic Execution Process
In order to understand how Dynamic SQL works and the various ways in which it can be applied to the many problems youll encounter, it is important to consider how Dynamic SQL is built. In addition, becoming familiar with the execution process used by SQL Server in order to parse and run the string of TSQL will make using Dynamic SQL a much easier process.
All Dynamic SQL follows three basic steps:
Create a string variable that will store the Dynamic SQL. Any variable name may be used.
Build a command string and store it in this variable.
Execute the command string.
The benefit of storing the TSQL command as a string is that you are free to use any string manipulation commands on it, building it in one or many steps. Now to tackle your original problem: how to select data from a table that is not defined until runtime. To accomplish this, you remove Person.Person from the string and replace it with a variable that you defined above:
DECLARE @sql_command NVARCHAR(MAX);
DECLARE @table_name NVARCHAR(100);
SELECT @table_name = 'Person.Person';
SELECT @sql_command = 'SELECT TOP 10 * FROM ' + @table_name;
EXEC (@sql_command);
The variable @table_name stores the name of the table you wish to query. Commonly, this would be passed in as a parameter, either from other stored procedures or an application that calls this directly. By building it into @sql_command , you gain the flexibility of querying any table you wish, without hard-coding it ahead of time. While this is a trivial example (how often will you want to select data in this fashion?), it provides the basis for thousands of applications, each of which can save immense time, resources, and complexity. Before diving further into the details of Dynamic SQL and its many uses, lets look at a more practical (and more complex) example of Dynamic SQL in action.
Dynamic SQL in Action
A common maintenance need is to run TSQL against many databases on a server. This maintenance could involve backing up databases, rebuilding indexes, reporting on critical data elements, or many other possibilities. If the database list never changes and no databases are ever renamed, you could hard-code names into each procedure and not worry about changing them in the future. This would work until the one day when you finally experience those inevitable changesmoving or renaming databaseswhich ultimately will break all of those valuable maintenance procedures. Its critical that your maintenance, monitoring, and reporting jobs operate with the highest level of reliability possible.
Listing shows a common example of a statement that could be used to run a backup against a single database, storing it on a local drive.
BACKUP DATABASE AdventureWorks2014
TO DISK='E:\SQLBackups\AdventureWorks2014.bak'
WITH COMPRESSION;
Listing 1-1.
Simple BACKUP Statement
This TSQL will back up the AdventureWorks2014 database to the SQLBackups folder on the E drive, using compression. If you want to perform a custom database backup on a subset of databases that all begin with the text AdventureWorks , for example, you would need to build TSQL that could adapt to collect a list of all databases with that name, and then perform backups on each of them separately. The following TSQL shows one way that this could be accomplished, using Dynamic SQL.
DECLARE @database_list TABLE
(database_name SYSNAME);
INSERT INTO @database_list
(database_name)
SELECT
name