Hi i have this example
DECLARE
#XML1 xml,
#XPath nvarchar(200),
#EncodedXPath nvarchar(200),
#Sql nvarchar(max),
#val nvarchar(20)
SET #XML1='
<Root>
<Device>
<Inspection>
<Status>OK</Status>
</Inspection>
</Device>
</Root>'
SELECT #XML1.query('/Root[1]/Device[1]/Inspection[1]/Status[1]')
SELECT #XML1.value('/Root[1]/Device[1]/Inspection[1]/Status[1]','varchar(5)')
SET #XPath = '/Root[1]/Device[1]/Inspection[1]/Status[1]'
SET #EncodedXPath = REPLACE(#XPath, '''', '''''')
SET #Sql = N'SELECT #XML1.query(''' + #EncodedXPath + N''')'
EXEC sp_executesql #Sql, N'#XML1 xml', #XML1
SET #Sql = N'SELECT #XML1.value(''' + #EncodedXPath + N''', ''varchar(5)'')'
EXEC sp_executesql #Sql, N'#XML1 xml', #XML1
if you execute the code above you get same result, but how can i assign the result of the dynamic sql to a variable using xpath? the below example return just the result of the execution but i want to get back the value 'OK'
EXEC #ret = sp_executesql #Sql, N'#XML1 xml', #XML1
The approach should be the same as getting result of any sp_executesql into a variable, no matter the sp_executesql contains XPath or just plain SQL.
This is one possible way, which also suggested in "How to get sp_executesql result into a variable?". Modify your dynamic SQL to have an output variable for storing the result of the XPath query. Then you can set your static variable -the one declared outside sp_executesql- from the output variable value :
....
SET #Sql = N'SET #ret = #XML1.value(''' + #EncodedXPath + N''', ''varchar(5)'')'
EXEC sp_executesql #Sql, N'#XML1 xml, #ret varchar(5) output', #XML1, #ret = #ret output
Related
This works:
declare #sql nvarchar(4000)
declare #minAmount decimal
set #sql = N'select PRODUCTGROUP
from dbo.ICMaster
where ONHAND > #minAmount'
set #minAmount = 400
print #sql
exec sp_executesql #sql, N'#minAmount decimal', #minAmount
But as soon as I change the #minAmount to nvarchar, it does not (no errors but the output is null). What am I missing ?
declare #sql nvarchar(4000)
declare #minAmount nvarchar(100)
set #sql = N'select PRODUCTGROUP
from dbo.ICMaster
where PRODUCTGROUP = #minAmount'
set #minAmount = '400'
print #sql
exec sp_executesql #sql, N'#minAmount nvarchar', #minAmount
I also tried :
set #minAmount = char(39)+'400'+char(39)
The value you query PRODUCTGROUP for is 4 not 400 because you forgot a size for the nvarchar:
exec sp_executesql #sql, N'#minAmount nvarchar(4000)', #minAmount
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
I am trying to call a stored procedure (with output variable) using sp_executesql but within another stored procedure. I wrote the following, but still not able to get trhough what that error means
This would be called from webservice code:
exec sp1 'obj1',#params
Here obj and params are of nvarchar(max)
Definition of sp1 is :
Alter procedure [dbo].[sp1 ]
#procname nvarchar(max),
#params nvarchar(max)
as
declare #temp varchar(15)
if #procname = 'obj1'
begin
set #params = #params + ',#Newval varchar(15) output'
EXEC sp_executesql #sp2,#params,#Newval=#temp OUTPUT
end
Definition of sp2:
Here I am returning #Newval
Error I am getting :
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near ','.
Also in 2 in place of exec statement , I have tried following:
EXEC sp_executesql #sp2, #params, #temp OUTPUT;
Results in the same error.
set #sql='sp2,' + ' #params ' + ',#params,#temp OUTPUT'
EXEC sp_executesql (#sql)
Also results in the same error.
I need this dynamic selection of stored procedures in sp1 and params is a nvarchar(max) string of parameters and their values, some of them are varchar and are embedded in ''value'' format but this string is fine as I am able to call the underlying sp2 with this.
Additional info, it it helps.
EXEC sp_executesql #sp2,#params,#Newval=#temp OUTPUT
in this #params is combination of keys and vlaue pairs for the final sp. something like :
'#key1="a",#key2="b"'
and so on, I can not predefined the #params but it is dynamic and it is working
fine when I run it with
exec (#sql)
Format while whole of the name, params are embedded in the #sql
If #params='' or NULL then your , before #Newval is irrelevant. I suggest you to check:
IF NULLIF(#params,'') IS NULL or #params IS NULL
SET #params = '#Newval varchar(15) output'
ELSE
SET #params = #params + ',#Newval varchar(15) output'
You are passing #sp2 maybe you need this:
ALTER PROCEDURE [dbo].[sp1]
#procname nvarchar(max),
#params nvarchar(max)
AS
DECLARE #temp varchar(15)
IF #procname = 'obj1'
BEGIN
SET #params = #params + ',#Newval varchar(15) output'
EXEC sp_executesql N'EXEC sp2 #someparam1, #someparam2, #Newval varchar(15) OUTPUT', #params, #someparam1 = 1, #someparam2 = 2, #Newval=#temp OUTPUT
END
EDIT
Working example:
USE [AdventureWorks]
GO
DECLARE #procname nvarchar(max) = 'EXEC [dbo].[uspGetWhereUsedProductID] #StartProductID, #CheckDate',
#params nvarchar(max) = '#StartProductID int, #CheckDate date'
EXEC sp_executesql #procname, #params, #StartProductID = 1, #CheckDate = '2015-10-17'
GO
DECLARE #sql NVARCHAR(max)
DECLARE #ParmDefinition NVARCHAR(500)
SET #sql = 'UPDATE [Table1] SET [Table1].[#columnName] = TEST';
SET #ParmDefinition = N'#columnName NVARCHAR(50)';
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'MyColumn';
When I run the above query, I get Invalid column name '#columnName'.. Clearly, the column name is not being replaced when the query is run.
In reality, my #sql variable is much larger and I have many columns I wish to update, thus I would like to avoid doing SET SQL = for all enumerations of the column name.
I'd like to declare the sql string once, and invoke the query with different values. e.g.:
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'MyColumn';
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'AnotherColumn';
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'YetAnotherColumn';
-- And so on
Is something like this possible?
Yes, you have to concatenate the variable outside the string. In other words:
SET #sql = 'UPDATE [Table1] SET [Table1].[' + #columnName + '] = t1.Value ' +
EDIT: Another solution we have used is to replace tokens in the base sql to construct a new sql variable for execution.
DECLARE #sql nvarchar(max) = 'SELECT #ColumnName FROM #TableName';
DECLARE #sql2 nvarchar(max) = REPLACE(REPLACE(#sql,'#ColumnName',#ColumnNameVariable),'#TableName',#TableNameVariable)
EXEC (#sql2)
...Some code that changes the values of #ColumnNameVariable and #TableNameVariable...
DECLARE #sql2 nvarchar(max) = REPLACE(REPLACE(#sql,'#ColumnName',#ColumnNameVariable),'#TableName',#TableNameVariable)
EXEC (#sql2)
And you'll notice that the Declaration and Exec of SQL2 are exactly the same lines in both cases. This lends itself to use in a LOOP if that is applicable. (Except that you wouldn't DECLARE #Sql2 in the loop...just populate/re-populate it).
First of all, kudos for trying to parameterize your dsql using sp_executesql. The problem is, you can only parameterize something you could put into a variable in the first place such as in a search predicate or select list.
However it's still possible; just concatenate the column name with your DSQL string, wrapping it with the quotename function
set #sql = 'update table1 set table1.' + quotename(#ColumnName) + ' = ...
I'm trying to get IDENT_CURRENT value on the linked server. I've created a stored procedure sp_current_identity on the remote server that has output parameter.
CREATE PROCEDURE [dbo].[sp_current_identity] ( #strTableName nvarchar(255), #intRowId int OUTPUT )
AS
BEGIN
select IDENT_CURRENT(#strTableName)
END
After that I have created two synonyms:sp_current_identity and sometable.
I need to execute sp_current_identity using sp_executesql (I'm creating a custom DataAtapter to work with synonyms via LLBLGEN 3.1). Please see the following example:
declare #p4 int
set #p4=NULL
exec sp_executesql N'SET XACT_ABORT ON; INSERT INTO [db].[dbo].[sometable] ([FieldName], [TableName], [UserField]) VALUES (#p1, #p3, #p4) ;
exec dbo.sp_current_identity #p5, #p2
;SET XACT_ABORT OFF',N'#p1 varchar(50),#p2 int output,#p3 varchar(50),#p4 varchar(50), #p5 varchar(200)',
#p1='test24',#p2=#p4 output,#p3='test24',#p4='test5',#p5='sometable'
select #p4
It works fine when this code is executed on the remote server (where sp_current_identity is local stored procedure), but it causes an exception when the code is executed on the local server.
Here is the error:
Procedure or function 'sp_current_identity' expects parameter '#strTableName', which was not supplied.
Thanks for your help!
Have you considered running EXEC remoteserver.database.dbo.sp_executesql 'dynamic SQL'; instead of trying to execute the dynamic SQL locally? The sp_current_identity procedure has to exist at the place where the query is actually executed, not where the query is called from.
I found that I had to assemble my dynamic call to the remote server in two steps. I was trying to get the Database ID:
DECLARE #sql nvarchar(4000)
DECLARE #parmDefinition nvarchar(500)
SET #parmDefinition = N'#retvalOUTside int OUTPUT'
SET #sql = 'SELECT TOP 1 #retvalOUT = database_id FROM [' + #ServerName + '].master.sys.databases WHERE name = ''''' + #dbname + ''''''
DECLARE #SPSQL nvarchar(4000) = '
DECLARE #DBID INT;
DECLARE #parmDefinition nvarchar(500);
SET #parmDefinition = N''#retvalOUT int OUTPUT'';
DECLARE #SQLinside nvarchar(400) =''' + #sql + ''';
EXEC [' + #ServerName + '].master.dbo' + '.sp_executeSQL #SQLinside, #parmDefinition, #retvalOUT = #retvalOUTside OUTPUT'
EXEC sp_executeSQL #SPSQL, #parmDefinition, #retvalOUTside=#DBID OUTPUT