MSSQL provides two types of commands for dynamic execution of SQL statements: exec and sp_executesql. Generally, sp_executesql is more advantageous. It provides an input and output interface, but exec does not. Another major benefit is that the execution plan can be reused using sp_executesql, which greatly provides the execution performance (for details in the following example ), you can also write more secure Code . Exec is more flexible in some cases. Unless you have a convincing reason to use exec, use sp_executesql whenever possible.
1. Exec usage
The exec command can be used either to execute a stored procedure or to execute a dynamic batch process. The following describes the second usage.
The following uses exec to demonstrate an example: Code 1
Declare @ tablename varchar (50), @ SQL nvarchar (max), @ orderid int; Set @ tablename = 'Orders '; Set @ orderid = 10251; set @ SQL = 'select * from' + quotename (@ tablename) + 'where orderid = '+ Cast (@ orderid as varchar (10 )) + 'order by orderid DESC 'exec (@ SQL); Note: Only one string variable can be contained in Exec brackets, but multiple variables can be concatenated. If we write Exec as follows:
Exec ('select top ('+ Cast (@ topcount as varchar (10) +') * from '+ quotename (@ tablename) + 'order by orderid DESC ');
The SQL Compiler reports an error and the compilation fails. If we do this:
Exec (@ SQL + @ sql2 + @ sql3); the compiler will pass;
Therefore, the best practice is to construct the code into a variable, and then use the variable as the input parameter of the exec command, so that it will not be restricted;
Exec does not provide interfaces
The interface here means that it cannot execute a batch containing a variable character. It doesn't seem to be clear at first glance. It doesn't matter. I have an instance below, you can see what it means.
Declare @ tablename varchar (50), @ SQL nvarchar (max), @ orderid int; Set @ tablename = 'Orders '; Set @ orderid = 10251; set @ SQL = 'select * from' + quotename (@ tablename) + 'where orderid = @ orderid order by orderid DESC 'exec (@ SQL ); the key lies in the Set @ SQL statement. If we run this batch, the compiler will generate an error.
MSG 137, Level 15, state 2, line 1
The scalar variable "@ orderid" must be declared ".
When using exec, if you want to access the variable, you must concatenate the variable content into a dynamically constructed code string, such as: Set @ SQL = 'select * from' + quotename (@ tablename) + 'where orderid = '+ Cast (@ orderid as varchar (10) + 'order by orderid DESC'
The content of the concatenation variable also has performance drawbacks. SQL Server creates a new execution plan for each query string, even if the query mode is the same. To demonstrate this, first clear the execution plan in the cache
DBCC freeproccache (this is not the content involved in this article, you can view the MS msdn)
Http://msdn.microsoft.com/zh-cn/library/ms174283.aspx
Run code 1 three times and assign the following three values to @ orderid: 10253. Then use the following code to query
Select cacheobjtype, objtype, usecounts, SQL from sys. syscacheobjects where SQL not like '% cach %' and SQL not like '% sys. % 'click F5 to run. The following query result is displayed:
We can see that each execution generates a compilation, and the Execution Plan is not fully reused.
Exec does not support output parameters except for input parameters in dynamic batch processing. By default, exec returns the query output to the caller. For example, the following code returns the number of all records in the orders table
Declare @ SQL nvarchar (max) set @ SQL = 'select count (orderid) from orders '; Exec (@ SQL); however, if you want to return the output to the variable in the call batch, the process is not that simple. Therefore, you must use the insert exec syntax to insert the output to a target table, and then obtain the value from the table and assign it to the variable, as shown in the following figure:
Declare @ SQL nvarchar (max), @ recordcount intset @ SQL = 'select count (orderid) from orders '; Create Table # T (TID INT ); insert into # T exec (@ SQL); Set @ recordcount = (select TID from # T) Select @ recordcountdrop table # T2, sp_executesql usage
The sp_executesql command is introduced later in SQL Server than the exec command, which provides better support for reusing execution plans.
To make a clear comparison with exec, let's look at if code 1 is used to replace exec with sp_executesql to see if we can get the expected result.
Declare @ tablename varchar (50), @ SQL nvarchar (max), @ orderid int, @ sql2 nvarchar (max); Set @ tablename = 'Orders '; Set @ orderid = 10251; set @ SQL = 'select * from' + quotename (@ tablename) + 'where orderid = '+ Cast (@ orderid as varchar (50 )) + 'order by orderid DESC 'exec sp_executesql @ SQL pay attention to the last line;
It turns out that it can run;
Sp_executesql Interface
The sp_executesql command is more flexible than the exec command because it provides an interface that also supports output parameters as well as input parameters. This function allows you to create query strings with parameters so that execution plans can be reused better than exec. The composition of sp_executesql is very similar to that of stored procedures, the difference is that you are building code dynamically. It consists of: fast code, parameter declaration, and parameter value assignment. Let's take a look at its syntax.
Exec sp_executesql
@ Stmt = <Statement>, -- similar to a stored procedure subject
@ Params = <Params>, -- similar to the stored procedure parameter Section
<Params assignment> -- similar to stored procedure call
The @ stmt parameter is the input dynamic batch processing. It can introduce the input or output parameters. It is the same as the main statement of the stored procedure, but it is dynamic, while the stored procedure is static, however, you can also use sp_executesql In the stored procedure;
@ Params the parameter is similar to the stored procedure header that defines the input/output parameters. In fact, the syntax of the stored procedure header is exactly the same;
@ <Params assignment> is similar to the exec part of the stored procedure.
To demonstrate that sp_executesql manages execution plans better than exec, I will use the code used in the exec discussed earlier.
Declare @ tablename varchar (50), @ SQL nvarchar (max), @ orderid int; Set @ tablename = 'Orders '; Set @ orderid = 10251; set @ SQL = 'select * from' + quotename (@ tablename) + 'where orderid = @ OID order by orderid DESC 'exec sp_executesql @ stmt = @ SQL, @ Params = n' @ OID as int', @ OID = @ orderid
Clear the execution plan in the cache before calling the code and checking the execution plan generated by the Code;
DBCC freeproccache
Execute the above dynamic code three times. Each execution is assigned a value different from @ orderid, and then query sys. syscacheobjects table, and pay attention to its output. The optimizer creates only one backup plan, and the plan is reused three times.
Select cacheobjtype, objtype, usecounts, SQL from SYS. syscacheobjects where SQL not like '% cache %' and SQL not like '% SYS. %' and SQL not like '% sp_executesql %'
Click F5 to run the task. The result shown in the following table is displayed;
Another powerful function of sq_executesql related to its interface is that you can use output parameters to return values of variables in the call batch processing. This function can be used to avoid returning data from a temporary table, so as to get more efficient code and less re-compilation. The syntax for defining and using output parameters is similar to the stored procedure. That is to say, You need to specify the output clause when declaring the parameter. For example, the static code below demonstrates how to use the output parameter @ P in dynamic batch processing to return the value to the variable @ I in the external batch processing.
Declare @ SQL as nvarchar (12), @ I as int; Set @ SQL = n' set @ P = 10'; Exec sp_executesql @ stmt = @ SQL, @ Params = n' @ P as int output', @ P = @ I outputselect @ I this code returns output 10
The above is the main difference between exec and sp_executesql. If you think something is wrong or you are not clear about it, Please also comment out ^_^