Set value of previously declared variables in Dynamic Select in SQL Server - sql-server

I'm working with a piece of dynamic SQL, posted below.
During testing when I Print #Query and run it, my variables get assigned. But when that extra level of indirection is added, and the #Query is run using Exec, the Select statement at the end returns nulls.
DECLARE #ETFirstPart varchar(max)
DECLARE #ETContactLines varchar(max)
DECLARE #ETAlternateContactOnlyLine varchar(max)
DECLARE #ETLastPart varchar(max)
SET #Query = N'SELECT #ETFirstPart = piv.HBAppCli1, #ETContactLines = piv.HBAppCli2a, #ETAlternateContactOnlyLine = piv.HBAppCli2b, #ETLastPart = piv.HBAppCli3
from (select EmailMessageType, EmailBody
FROM ' + #dbSharedServer + '.dbShared.dbo.EmailMessage e
) ac
pivot (max(EmailBody)
for EmailMessageType in (HBAppCli1, HBAppCli2a, HBAppCli2b, HBAppCli3)
) piv'
PRINT #Query
EXEC (#Query)
SELECT #ETFirstPart, #ETContactLines, #ETAlternateContactOnlyLine, #ETLastPart
How can I get the variables assigned to the selected values in the dynamic select?

You need to use sp_executesql. Something like below:
DECLARE #sql nvarchar(max)
set #sql = N'SELECT #ETFirstPart = piv.HBAppCli1, #ETContactLines = piv.HBAppCli2a, #ETAlternateContactOnlyLine = piv.HBAppCli2b, #ETLastPart = piv.HBAppCli3
from (select EmailMessageType, EmailBody
FROM ' + #dbSharedServer + '.dbShared.dbo.EmailMessage e
) ac
pivot (max(EmailBody)
for EmailMessageType in (HBAppCli1, HBAppCli2a, HBAppCli2b, HBAppCli3)
) piv'
exec sp_executesql #sql, N'#ETFirstPart varchar(max) out, #ETContactLines varchar(max) out, #ETAlternateContactOnlyLine varchar(max) out, #ETLastPart varchar(max) out', #ETFirstPart out, #ETContactLines out, #ETAlternateContactOnlyLine out, #ETLastPart out
SELECT #ETFirstPart, #ETContactLines, #ETAlternateContactOnlyLine, #ETLastPart

Related

Execute dynamic query that executes another stored procedure

I have a query like this:
DECLARE #TaskId UNIQUEIDENTIFIER
DECLARE #TaskName VARCHAR(255) = 'MasterSet'
DECLARE #sql NVARCHAR(MAX)
DECLARE #StartingDateTask DATETIME2 = (SELECT TOP 1 [Date]
FROM [TaskStatusAudit]
WHERE [TaskId] = 'A1FDFC16-904D-4560-B19D-5E7D4FEB1C2B'
AND [TaskStatusName] = 'IN-PROGRESS')
DECLARE #EndingDateTask DATETIME2 = (SELECT TOP 1 [Date]
FROM [TaskStatusAudit]
WHERE [TaskId] = 'A1FDFC16-904D-4560-B19D-5E7D4FEB1C2B'
AND [TaskStatusName] = 'COMPLETED')
SET #sql = N'SELECT dbo.TotalMinuteRange(#StartingDateTask,#EndingDateTask) as ' + quotename(#TaskName) + N''
EXEC sp_executesql #sql
Problem is when I execute it I get this error:
Must declare the scalar variable "#StartingDateTask".
Any ideas why I getting that if I declare my variable correctly? Regards
When executing sp_executesql you need to declare and pass the variables to sp_executesql something like..
SET #sql = N'SELECT dbo.TotalMinuteRange(#StartingDateTask,#EndingDateTask) as '
+ quotename(#TaskName) + N''
exec sp_executesql #sql
, N'#StartingDateTask DATETIME2 , #EndingDateTask DATETIME2'
, #StartingDateTask
, #EndingDateTask
Second parameter is the variable declaration parameter followed by the actual variables separately.
You can also do like taking a parameters variable and assign it.
declare #params nvarchar(100)
set #params='#StartingDateTask DATETIME2,#EndingDateTask DATETIME2'
SET #sql = N'SELECT dbo.TotalMinuteRange(#StartingDateTask,#EndingDateTask) as '
+ quotename(#TaskName) + N''
exec sp_executesql #sql
, #params
, #StartingDateTask
, #EndingDateTask

How can I use a local variable in SELECT FROM?

I declared a variable #Obj and assign a complete table name 'ODS..Account' to it.
DECLARE #Obj VARCHAR(255)
Then I used it in a query immediately after FROM Clause. I perceive it is just a string, unable to act as a table object. So how can I fix the code to get it works? Cheers
INSERT Control.dbo.Consistency_Check
(Table_Name
,Schema_Name
,Id
,Incremental_DateTime_Column
)
SELECT
#Tab
,'ODS'
,Id
,SystemModstamp
FROM
#Obj )
You can use a local variable as a scalar value, not as a function. To do this, you need dynamic SQL:
declare #sql varchar(max);
select #sql = '
INSERT Control.dbo.Consistency_Check(Table_Name, Schema_Name, Id, Incremental_DateTime_Column)
SELECT ''#Tab'', 'ODS', Id, SystemModstamp
FROM #Tab
';
select #sql = replace(#sql, '#tab', #tab);
exec sp_executesql #sql;
Slightly different way of doing it with dynamic SQL:
DECLARE #Obj VARCHAR(255) = 'dbo.table'
DECLARE #SQL NVARCHAR(MAX) = ''
SET #SQL = #SQL +
'INSERT Control.dbo.Consistency_Check
(Table_Name
,Schema_Name
,Id
,Incremental_DateTime_Column
)
SELECT
#Tab
,''ODS''
,Id
,SystemModstamp
FROM
' + #Obj + ''
EXEC (#SQL)
You cannot. You probably want to use dynamic query. i.e. workout the SQL query string into a variable and exec using sp_executesql.
You may use the same variable name in the dynamic SQL but I changed it to #p_Tab for the example.
DECLARE #Tab int = 3
DECLARE #SQLString nvarchar(500)
DECLARE #ParmDefinition nvarchar(500) = N'#p_Tab int';
Declare #TableName nvarchar(100) = 'ODS..Account'
/* Build the SQL string dynamicly.*/
SET #SQLString = N'INSERT Control.dbo.Consistency_Check
(Table_Name
,Schema_Name
,Id
,Incremental_DateTime_Column
)
SELECT
#p_Tab
,''ODS''
,Id
,SystemModstamp
FROM
'+ #TableName
EXECUTE sp_executesql #SQLString, #ParmDefinition,
#p_Tab = #Tab
Further reference: https://msdn.microsoft.com/en-us/library/ms188001.aspx

How can I use a variable inside OPENQUERY

I am getting an error running the code below. I believe it as to do with the number of single quotes used.
How can I set a variable inside OPENQUERY command?
#declare #myStr varchar(6)
set #myStr = 'Test1'
SELECT *
FROM OPENQUERY("192.168.1.1",'SET FMTONLY OFF; EXEC spNewTest #Param1 = ''+ #myStr +''')
Click to see the error message
Regards,
Elio Fernandes
If you want to create a single quote within a string you have to put in two single quotes. For example:
'''this is a string''' would be a string containing the following:
'this is a string'
So for your problem, you have to change your code to this:
#declare #myStr varchar(6)
set #myStr = 'Test1'
SELECT *
FROM OPENQUERY("192.168.1.1",'SET FMTONLY OFF; EXEC spNewTest #Param1 = '''+ #myStr +'''')
I just found the answer for my question, so I thought sharing it with you.
DECLARE #QUERY VARCHAR(MAX)
DECLARE #TSQL VARCHAR(100)
DECLARE #SP VARCHAR(50)
DECLARE #PARAMETERS VARCHAR(MAX)
DECLARE #PARAM1 VARCHAR(50)
DECLARE #PARAM2 VARCHAR(50)
SET #TSQL = N'SELECT * FROM OPENQUERY([192.168.1.1], ''SET FMTONLY OFF; '
SET #SP = 'EXEC spNewTest '
SET #PARAM1 = '#Type='''+ QUOTENAME('Test','''') + ''''
SET #PARAM2 = '#Year='''+ QUOTENAME('2016','''') + ''''
SET #PARAMETERS = #PARAM1 + ', ' + #PARAM2
SET #QUERY = #TSQL + #SP + #PARAMETERS + ''')'
EXECUTE (#QUERY)
Thanks

how to assign results from exec to variable

How do I assign the results of an exec command to a variable. like the below, so when I do select #sql2 I get the result of the executed varchar sql.
declare #sql varchar(500)
declare #sql2 varchar(max)
set #sql = 'SELECT
PDB.OutletBrandID, OB.BrandName
FROM
ProductDistributionBrand PDB
INNER JOIN
[IND_roadchef].dbo.OutletBrands OB
ON
PDB.OutletBrandID = OB.OutletBrandID
FOR XML PATH(''ProductDistributionBrandDetail''),ROOT(''ProductDistributionBrandDetails''),TYPE'
--select #sql
set #sql2 = exec(#sql)
select #sql2
Use an output param:
declare #sql nvarchar(500)
declare #xml XML
set #sql = 'set #xml = (SELECT ..... FOR XML PATH(''ProductDistributionBrandDetail''),ROOT(''ProductDistributionBrandDetails''),TYPE)'
EXEC sp_executesql #sql, N'#xml XML output', #xml = #xml OUTPUT
select #xml
You can use Table Variables. Try like this,
DECLARE #sql TABLE (col1 VARCHAR(500))
DECLARE #sql2 VARCHAR(max)
SET #sql2 = 'SELECT
PDB.OutletBrandID, OB.BrandName
FROM
ProductDistributionBrand PDB
INNER JOIN
[IND_roadchef].dbo.OutletBrands OB
ON
PDB.OutletBrandID = OB.OutletBrandID
FOR XML PATH(''ProductDistributionBrandDetail''),ROOT(''ProductDistributionBrandDetails''),TYPE'
INSERT INTO #sql
EXEC (#sql2)
SELECT *
FROM #sql
Please see reference from this link it will show you how to use output parameters
https://support.microsoft.com/en-us/kb/262499

size limit for nvarchar(max)

i am trying to execute a sql query string which has thousands of characters in t-sql. data type using to hold this query is nvarchar(max). but using this i can hold only 67594 characters. but my query has more characters than this.
does anybody has any idea why nvarchar(max) is holding up to 67594 characters only? the nvarchar(max) should hold up to 2GB data. isn't it?
the procedure which i am running is:
create procedure test
(
#snapshotid1 nvarchar(10),
#snapshotid2 nvarchar(10),
#version1 nvarchar(100),
#version2 nvarchar(100)
) AS DECLARE
#sql nvarchar(max),
#whereClause1 nvarchar(500),
#whereClause2 nvarchar(500),
#fromClause1 nvarchar(100),
#fromClause2 nvarchar(100)
BEGIN
set #sql = '';
set #sql = #sql + N'
select v1.v1_brand, version1total, version2total, version1total - version2total as varience from (
select "C - Brand" as v1_brand,
case ' + #period + ' when ''Jan'' then sum(Period1InvoicedAmount)
when ''Feb'' then
.
.
.
END
regards
Subash Amara
Can't reproduce. But! don't think a proper TSQL concatenation can't handle large string. You probably have a problem somewhere in your script. It depends what error are you getting.
Here's a little proof of concept you can run.
First write this script:
DECLARE #sql nvarchar(max) = ''
SET #sql = N'SELECT fld = newid()'
-- (PLACEHOLDER) --
SELECT DATALENGTH(#sql)
EXEC(#sql)
Then run this script and copy the rows...
SELECT TOP 2000
q = 'SET #sql = #sql + N''UNION ALL SELECT fld = newid()'''
FROM sys.syscolumns t1, sys.syscolumns t2
...and paste it instead of -- (PLACEHOLDER) --, so you have...
DECLARE #sql nvarchar(max) = ''
SET #sql = N'SELECT fld = newid()'
SET #sql = #sql + N'UNION ALL SELECT fld = newid()'
SET #sql = #sql + N'UNION ALL SELECT fld = newid()'
...(totals 2000 lines)...
SET #sql = #sql + N'UNION ALL SELECT fld = newid()'
SELECT DATALENGTH(#sql)
EXEC(#sql)
When you execute this, you will see that data length is 120040 (well above 67594) and it outputs 2001 rows, as it should.
However, if you try to PRINT or SELECT your dynamically created string in SSMS, like:
PRINT #sql
SELECT #sql
...you will get truncated results.

Resources