EXEC/EXECUTE
;sp_executesql
DECLARE @sql varchar(1000) DECLARE @columnList varchar(75) DECLARE @city varchar(75) SET @columnList = 'CustomerID, ContactName, City' SET @city = 'London' SELECT @sql = ' SELECT CustomerID, ContactName, City ' + ' FROM dbo.customers WHERE 1 = 1 ' SELECT @sql = @sql + ' AND City LIKE ''' + @city + '''' EXEC (@sql)
select @sql
, the result will be the following: SELECT CustomerID, ContactName, City FROM customers WHERE City = 'London'
@city
like this set @city = '''DROP TABLE customers--'''
- and the result will be sad, because the select
operation succeeds, as DROP TABLE customers
operation.EXEC(@sql1 + @sql2 + @sql3).
(@sql1 + @sql2 + @sql3)
will be performed, and then the general command will be executed. You also need to remember that a general limitation is imposed on the EXEC command parameter of 4000 characters.sp_executesql
? - It's easier for a developer to write code and debug it, because The code will be written almost like a normal Sql query. DECLARE @sqlCommand varchar (1000) DECLARE @columnList varchar (75) DECLARE @city varchar (75) SET @city = 'London' SET @sqlCommand = 'SELECT CustomerID, ContactName, City FROM customers WHERE City = @city' EXECUTE sp_executesql @sqlCommand, N'@city nvarchar(75)', @city = @city
EXECUTE
when using sp_executesql
, no type casting is necessary if we use typed parameters sp_executesql.
SELECT q.TEXT,cp.usecounts,cp.objtype,p.*, q.*, cp.plan_handle FROM sys.dm_exec_cached_plans cp CROSS apply sys.dm_exec_query_plan(cp.plan_handle) p CROSS apply sys.dm_exec_sql_text(cp.plan_handle) AS q WHERE q.TEXT NOT LIKE '%sys.dm_exec_cached_plans %' and cp.cacheobjtype = 'Compiled Plan' AND q.TEXT LIKE '%customers%'
sp_executesql
is the ability to return a value through the OUT
parameter.Select
. Why we did not do that? There were not many reports in the project to implement SSRS there.select
and on the server side already create the required “form” DataSet . Yes, the problem was solved initially, when there was very little data on the goods. As soon as there was a lot of data, the time for collecting the report became beyond the established timeout .Pivot
in sql. Yes, a great solution when you know that you have only these attributes, and there will be no new ones. And what to do when the number of attributes often changes. And again, for each group of objects we have our own set of attributes, we will again return to creating a procedure for each group of objects. Not a very convenient solution, is it? SELECT p.Id as ProductID, p.Name as [], pcp.Name as PropertiesName, vpp.Value as Value FROM dbo.Products p INNER JOIN dbo.PropertiesCategoryOfProducts pcp ON pcp.CategoryOfProductsId = p.CategoryOfProductsId INNER JOIN dbo.ValueOfProductProperty vpp ON vpp.ProductID = p.Id and vpp.PropertiesCategoryOfProductsId = pcp.Id where p.CategoryOfProductsId = @CategoryOfProductsId
SELECT p.Id as ProductID, p.Name as [], pcp.Name as PropertiesName, vpp.Value as Value FROM dbo.Products p INNER JOIN dbo.PropertiesCategoryOfProducts pcp ON pcp.CategoryOfProductsId = p.CategoryOfProductsId INNER JOIN dbo.ValueOfProductProperty vpp ON vpp.ProductID = p.Id and vpp.PropertiesCategoryOfProductsId = pcp.Id where p.CategoryOfProductsId = @CategoryOfProductsId declare @CategoryOfProductsId int = 1 declare @PivotColumnHeaders nvarchar(max)= REVERSE(STUFF(REVERSE((select '[' + Name + ']' + ',' as 'data()' from dbo.PropertiesCategoryOfProducts t where t.CategoryOfProductsId = @CategoryOfProductsId FOR XML PATH('') )),1,1,'')) if(@PivotColumnHeaders>'') declare @PivotTableSQL nvarchar(max) BEGIN SET @PivotTableSQL = N' SELECT * from (SELECT p.Id as ProductID, p.Name as [], pcp.Name as PropertiesName, vpp.Value as Value FROM dbo.Products p INNER JOIN dbo.PropertiesCategoryOfProducts pcp ON pcp.CategoryOfProductsId = p.CategoryOfProductsId INNER JOIN dbo.ValueOfProductProperty vpp ON vpp.ProductID = p.Id and vpp.PropertiesCategoryOfProductsId = pcp.Id where p.CategoryOfProductsId = @CategoryOfProductsId ) as Pivot_Data PIVOT ( MIN(Value) FOR PropertiesName IN ( ' + @PivotColumnHeaders + ' ) ) AS PivotTable ' EXECUTE sp_executesql @PivotTableSQL, N'@CategoryOfProductsId int', @CategoryOfProductsId = @CategoryOfProductsId; END
declare @CategoryOfProductsId int = 1
declare @CategoryOfProductsId int = 1
Pivot
function - declare @PivotColumnHeaders nvarchar(max)= REVERSE(STUFF(REVERSE((select '[' + Name + ']' + ',' as 'data()' from dbo.PropertiesCategoryOfProducts t where t.CategoryOfProductsId = @CategoryOfProductsId FOR XML PATH('') )),1,1,''))
Pivot
function will be substituted from @PivotColumnHeaders
@PivotColumnHeaders
select @PivotTableSQL
, we will get the query that we would have to write manually without using dynamic sql.Source: https://habr.com/ru/post/272807/
All Articles