I have the below code that is not working as expected:
DECLARE #MySelect varchar(max), #MyRecipients varchar(max), #MyId
char(4),#MyResult varchar(max);
SET #MyId = '1';
SET #MySelect = 'SELECT SQL_Script FROM AutoSendMail.dbo.A01_St WHERE
ID =' + #MyId;
USE msdb
EXEC sp_send_dbmail
#profile_name='Operator',
#recipients='Mail#test.com',
#subject='Mail test',
#body= 'This is a test-mail',
#mailitem_id='1',
#query= #MyResult,
#attach_query_result_as_file = 1
I need to save the result of the select query: #MySelect into the variable #MyResult, because I need to send the result of the SELECT via Mail. But I can't find a way to do just that. The query should return a single string value.
You can do this without dynamic SQL, like so:
DECLARE #MyRecipients VARCHAR(MAX) ,
#MyId CHAR(4) = '1' ,
#MyResult VARCHAR(MAX);
SET #MyId = '1';
SELECT TOP 1
#MyResult = SQL_Script
FROM AutoSendMail.dbo.A01_St
WHERE ID = #MyId
USE msdb
EXEC sp_send_dbmail #profile_name = 'Operator', #recipients = 'Mail#test.com',
#subject = 'Mail test', #body = 'This is a test-mail', #mailitem_id = '1',
#query = #MyResult, #attach_query_result_as_file = 1
Not that you need dynamic SQL, but please note, that doing this:
SET #MySelect = 'SELECT SQL_Script FROM AutoSendMail.dbo.A01_St WHERE ID =' + #MyId;
Does not execute any code, it simply sets the value of #MySelect. You would need to call an execute command to run the SQL:
EXEC SP_EXECUTESQL #MySelect
You can declare table variable, insert into it the results of executing your query and then select into your result variable:
DECLARE #t TABLE(SQL_Script varchar(max))
INSERT INTO #t EXEC(#MySelect)
SELECT TOP 1 #MyResult = SQL_Script FROM #t
You can also use sp_executesql procedure with output parameters like:
SET #MyId = '1';
SET #MySelect = 'SELECT #MyResult = SQL_Script FROM AutoSendMail.dbo.A01_St WHERE
ID =' + #MyId;
EXEC sp_executesql #MySelect, '#MyResult varchar(max) OUTPUT', #MyResult OUTPUT
How about this?
select #MyResult = stuff((
select ',' + convert(nvarchar(20), SQL_Script)
from AutoSendMail.dbo.A01_St
where ID = #MyId
for
xml path('')
), 1, 1, '')
This outputs a comma delimited string though
Related
I have a piece of dynamic SQL I need to execute, I then need to store the result into a variable.
I know I can use sp_executesql but can't find clear examples around about how to do this.
If you have OUTPUT parameters you can do
DECLARE #retval int
DECLARE #sSQL nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #tablename nvarchar(50)
SELECT #tablename = N'products'
SELECT #sSQL = N'SELECT #retvalOUT = MAX(ID) FROM ' + #tablename;
SET #ParmDefinition = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #sSQL, #ParmDefinition, #retvalOUT=#retval OUTPUT;
SELECT #retval;
But if you don't, and can not modify the SP:
-- Assuming that your SP return 1 value
create table #temptable (ID int null)
insert into #temptable exec mysp 'Value1', 'Value2'
select * from #temptable
Not pretty, but works.
DECLARE #vi INT
DECLARE #vQuery NVARCHAR(1000)
SET #vQuery = N'SELECT #vi= COUNT(*) FROM <TableName>'
EXEC SP_EXECUTESQL
#Query = #vQuery
, #Params = N'#vi INT OUTPUT'
, #vi = #vi OUTPUT
SELECT #vi
DECLARE #tab AS TABLE (col1 VARCHAR(10), col2 varchar(10))
INSERT into #tab EXECUTE sp_executesql N'
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2
UNION ALL
SELECT 1 AS col1, 2 AS col2'
SELECT * FROM #tab
Return values are generally not used to "return" a result but to return success (0) or an error number (1-65K). The above all seem to indicate that sp_executesql does not return a value, which is not correct. sp_executesql will return 0 for success and any other number for failure.
In the below, #i will return 2727
DECLARE #s NVARCHAR(500)
DECLARE #i INT;
SET #s = 'USE [Blah]; UPDATE STATISTICS [dbo].[TableName] [NonExistantStatisticsName];';
EXEC #i = sys.sp_executesql #s
SELECT #i AS 'Blah'
SSMS will show this
Msg 2727, Level 11, State 1, Line 1
Cannot find index 'NonExistantStaticsName'.
If you want to return more than 1 value use this:
DECLARE #sqlstatement2 NVARCHAR(MAX);
DECLARE #retText NVARCHAR(MAX);
DECLARE #ParmDefinition NVARCHAR(MAX);
DECLARE #retIndex INT = 0;
SELECT #sqlstatement = 'SELECT #retIndexOUT=column1 #retTextOUT=column2 FROM XXX WHERE bla bla';
SET #ParmDefinition = N'#retIndexOUT INT OUTPUT, #retTextOUT NVARCHAR(MAX) OUTPUT';
exec sp_executesql #sqlstatement, #ParmDefinition, #retIndexOUT=#retIndex OUTPUT, #retTextOUT=#retText OUTPUT;
returned values are in #retIndex and #retText
Declare #variable int
Exec #variable = proc_name
DECLARE #ValueTable TABLE
(
Value VARCHAR (100)
)
SELECT #sql = N'SELECT SRS_SizeSetDetails.'+#COLUMN_NAME+' FROM SRS_SizeSetDetails WHERE FSizeID = '''+#FSizeID+''' AND SRS_SizeSetID = '''+#SRS_SizeSetID+'''';
INSERT INTO #ValueTable
EXEC sp_executesql #sql;
SET #Value='';
SET #Value = (SELECT TOP 1 Value FROM #ValueTable)
DELETE FROM #ValueTable
This worked for me:
DECLARE #SQL NVARCHAR(4000)
DECLARE #tbl Table (
Id int,
Account varchar(50),
Amount int
)
-- Lots of code to Create my dynamic sql statement
insert into #tbl EXEC sp_executesql #SQL
select * from #tbl
Here's something you can try
DECLARE #SqlStatement NVARCHAR(MAX) = ''
,#result XML
,#DatabaseName VARCHAR(100)
,#SchemaName VARCHAR(10)
,#ObjectName VARCHAR(200);
SELECT #DatabaseName = 'some database'
,#SchemaName = 'some schema'
,#ObjectName = 'some object (Table/View)'
SET #SqlStatement = '
SELECT #result = CONVERT(XML,
STUFF( ( SELECT *
FROM
(
SELECT TOP(100)
*
FROM ' + QUOTENAME(#DatabaseName) +'.'+ QUOTENAME(#SchemaName) +'.' + QUOTENAME(#ObjectName) + '
) AS A1
FOR XML PATH(''row''), ELEMENTS, ROOT(''recordset'')
), 1, 0, '''')
)
';
EXEC sp_executesql #SqlStatement,N'#result XML OUTPUT', #result = #result OUTPUT;
SELECT DISTINCT
QUOTENAME(r.value('fn:local-name(.)', 'VARCHAR(200)')) AS ColumnName
FROM #result.nodes('//recordset/*/*') AS records(r)
ORDER BY ColumnName
This was a long time ago, so not sure if this is still needed, but you could use ##ROWCOUNT variable to see how many rows were affected with the previous sql statement.
This is helpful when for example you construct a dynamic Update statement and run it with exec. ##ROWCOUNT would show how many rows were updated.
Here is the definition
I am trying to write a dynamic query. Let's say i have a table like below, which represents the hierarchy level of a sales agent:
AgentNumber Level1Agent Level2Agent Level3Agent Level4Agent Level5Agent
1122334455 1122334499 1122334488 1122334477 1122334466 1122334455
I want to be able to dynamically select a level based on a specified agent. My EXECUTE statement seems to work correctly, but how do I get the result stored in a variable I can use later? Every answer I have found seems to only get me a success return variable, not the actual query result.
Below is my code:
DECLARE #level INT = 1;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
DECLARE #whereclause NVARCHAR(35) = CONCAT('WHERE AgentNumber = ',#agent);
DECLARE #qry NVARCHAR(300) = 'SELECT ' + #colname + ' FROM dbo.TABLE ' + #whereclause;
DECLARE #up NVARCHAR(10);
EXECUTE sp_executesql #qry, #up OUT
SELECT #up
The output of #up is NULL. If I change the last two lines to:
EXECUTE #up = sp_executesql #qry
SELECT #up
Now the output of #up is 0.
I want the output of 1122334499 and I need it stored in a variable that can later be used and inserted into a table.
Here is a fully functional example of how you can do this. Notice this is using a parameterized where clause and quotename around the column name in the dynamic sql to prevent sql injection.
if OBJECT_ID('tempdb..#Agents') is not null
drop table #Agents
create table #Agents
(
AgentNumber char(10)
, Level1Agent char(10)
, Level2Agent char(10)
, Level3Agent char(10)
, Level4Agent char(10)
, Level5Agent char(10)
)
insert #Agents
select '1122334455', '1122334499', '1122334488', '1122334477', '1122334466', '1122334455'
DECLARE #level INT = 3;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
declare #agentout char(10)
DECLARE #qry NVARCHAR(300) = 'SELECT #agent_out = ' + quotename(#colname) + ' FROM #Agents WHERE AgentNumber = #agentin';
EXECUTE sp_executesql #qry, N'#agentin char(10), #agent_out char(10) output', #agentin = #agent, #agent_out = #agentout output
select #agentout
You can try this :
DECLARE #level INT = 1;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
DECLARE #whereclause NVARCHAR(35) = CONCAT('WHERE AgentNumber = ',#agent);
DECLARE #qry NVARCHAR(300) = 'SELECT #agentout=' + #colname + ' FROM dbo.TABLE ' + #whereclause;
DECLARE #up NVARCHAR(10);
EXECUTE sp_executesql #qry, N'#agentout NVARCHAR(10) OUTPUT', #agentout=#up OUTPUT
SELECT #up
Create a variable table and makes your query insert the results you want there. Something like this:
declare #results table(field1 varchar(max), field2 varchar(max));
declare #sqlStatement varchar(max);
set #sqlStatement = 'insert into #results(field1, field2) select field1, field2 from table';
EXECUTE #sqlStatement;
select * from #results; --It will print the results from your sql statement!
When executing below sql server i am unable to pass #AKM parameter in the code how ever i am able to reproduce the same which doing in simple query's. However i am able to pass variable for id as it is an int type but #akm is in charecter
CREATE PROCEDURE [dbo].[sp_akm_test]
#AKM NVARCHAR(128),
#Anlsid Int
AS
DECLARE #Sql1 NVARCHAR(MAX);
DECLARE #type NVARCHAR(MAX);
BEGIN
SELECT TOP 1 #type= sample_type FROM ' + #RDM +'.dbo.analysis where ID= '#id
PRINT(#type)
IF (#type = 8017)
BEGIN
SET #Sql1 = N'select sample_n FROM'+ QUOTENAME(#AKM) +'..sample'
END
ELSE
Begin
SET #Sql1 = N'select sampleid FROM'+ QUOTENAME(#AKM) +'..sample'
END
EXECUTE sp_executesql #Sql1
END
I guess you need something like this
declare #RDM sysname = ???? -- pass the db name, missing in your code
declare #sql nvarchar(4000)= '',#type int
set #sql = '
SELECT TOP 1 #type= sample_type FROM ' + quotename(#RDM) +'.dbo.rdm_analysis where ID=110'
exec sp_executesql #sql,N'#type int output',#type = #type output
SET #Sql1 = '
select case when #type = 8017 then sample_n else sampleid end
FROM'+ QUOTENAME(#AKM) +'..sample'
exec sp_executesql #sql1,N'#type int',#type
How to create an insert with select query in a variables using SQL Server?
Here for example:
DECLARE #sqlCommand nvarchar(MAX)
DECLARE #odbname varchar(30)
DECLARE #m VARCHAR(20)
DECLARE #id VARCHAR(20)
DECLARE #br VARCHAR(30)
DECLARE #ndbname VARCHAR(30)
SET #ndbname='databasename'
SET #id = 2
SET #odbname = 'olddatabasename'
SET #br = 2
SET #m = 9
DECLARE #insert VARCHAR(MAX)
SET #insert = 'INSERT INTO'+ #ndbname+'.[pm]([pmId],[pmCode],[pmName])'
EXEC (#insert)
SET #sqlCommand = 'SELECT #id AS spID,[spCode],[spName] `enter code here`FROM' + #0dbname+'.[sp] where spbID = #br and spID = #m'
EXECUTE sp_executesql #sqlCommand, N'#br nvarchar(75),#m nvarchar(75),#id VARCHAR(20)',#br = #br,#m=#m,#id=#id
Actually I needed a select query executed in insert query ie, selected data inserted in to another database table
SET #insert='INSERT INTO'+ #ndbname+'.[pm]([pmId],[pmCode],[pmName])'
SET #sqlCommand = #insert + ' ' +'SELECT #id AS spID,[spCode],[spName] `enter code here`FROM' + #0dbname+'.[sp] where spbID = #br and spID = #m'
EXECUTE sp_executesql #sqlCommand, N'#br nvarchar(75),#m nvarchar(75),#id VARCHAR(20)',#br = #br,#m=#m,#id=#id
There are quite a few flaws:
You try to execute the INSERT alone
If you state a dbName, you must specify the schema (is it "dbo"?)
You're letting out spaces
If you change to this
SET #insert='INSERT INTO'+ #ndbname+'.[pm]([pmId],[pmCode],[pmName])'
SET #sqlCommand = #insert + ' SELECT #id AS spID,[spCode],[spName] `enter code here`FROM' + #odbname+'.[sp] where spbID = #br and spID = #m'
PRINT #sqlCommand
You'll get this:
INSERT INTOdatabasename.[pm]([pmId],[pmCode],[pmName]) SELECT #id AS spID,[spCode],[spName] `enter code here`FROMolddatabasename.[sp] where spbID = #br and spID = #m
But it should be something like this
INSERT INTO databasename.[schema].[pm]([pmId],[pmCode],[pmName])
SELECT #id,[spCode],[spName]
FROM olddatabasename.[schema].[sp]
where spbID = #br and spID = #m
General hints:
Don't use dynamic SQL if you don't need it
If you build dynamic sql don't try to execute it. Rather print it, copy it to a query window and analyze if it is OK
I have the following stored procedure:
ALTER proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int
as
DECLARE #value nvarchar(10)
SET #value = 's'+CONVERT(nvarchar(50),#snum)
DECLARE #sqlText nvarchar(1000);
DECLARE #sqlText2 nvarchar(1000);
DECLARE #sqlText3 nvarchar(1000);
declare #g nvarchar(50) = '''g1'''
SET #sqlText = N'SELECT ' + #value + N' FROM dbo.GrideBtable'
SET #sqlText2 = ' where Gnumber = '+#g --here is the problem it error invalid column name -- the #g is value from the table condition
set #sqlText3 = #sqlText+#sqlText2
Exec (#sqlText3) -- here how can i save the result of the exec into varibale
declare #sal nvarchar(50) = #sqlText3
insert employ (name,Snumber,Gnumber,Salary) values(#name,#snum,#gnum,#sal)
QUESTION: How to put in condition variable gets value from the table when i exec it it think that the #g is column but its not its a value from the table to test it so i display one value after the exec the other QUESTION is how to save the result from the exec in variable and then use that value
I'm using SQL Server 2008 (9.0 RTM)
This will be a stored procedure
Thanks in advance
Not sure why you would go through all the loops to insert into the table where you can have a simple insert query like ..
ALTER PROC dbo.[insertperoll] #name nvarchar(50) , #snum int , #gnum int
AS
insert employ (name, Snumber, Gnumber, Salary)
select #name
, #sum
, #gnum
, case when #snum = 1 then s1
when #snum = 2 then s2
when #snum = 3 then s3
when #snum = 4 then s4
end as Salary
from dbo.GrideBtable
where Gnumber = #gnum
If your intent is to have the proc retrieve a salary value from a column determined from the parameter snum and then make an insert into employ using the values passed as parameters and the salary retrieved I think you could refactor your procedure to this:
CREATE proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int AS
DECLARE #g NVARCHAR(50) = 'g1'
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'INSERT employ (name,Snumber,Gnumber,Salary) '
SET #sql += N'SELECT ' + QUOTENAME(#name, '''')
SET #sql += N', ' + CAST(#snum AS NVARCHAR(50))
SET #sql += N', ' + CAST(#gnum AS NVARCHAR(50))
SET #sql += N', s' + CAST(#snum AS NVARCHAR(50))
SET #sql += N' FROM dbo.GrideBtable'
SET #sql += N' WHERE Gnumber = ' + QUOTENAME(#g, '''')
EXEC (#sql)
Of course you could add the #g variable to the procedure parameters instead of having it hard coded in the procedure and call it as:
EXEC insertperoll #name='john', #snum=10, #gnum=100, #g='g1'
Sample SQL Fiddle (with some assumptions made about table structure)
You could do this using sp_executesql instead of exec() since this will allow you to use parameters, you can use an output parameter to get the value from the query:
DECLARE #SQL NVARCHAR(MAX) = N'SELECT #val = ' + CONVERT(NVARCHAR(10),#snum) +
N' FROM dbo.GrideBtable WHERE Gnumber = #G1';
DECLARE #val INT; -- NOT SURE OF DATATYPE REQUIRED
EXECUTE sp_executesql #SQL, N'#G1 VARCHAR(20), #val INT OUT', 'G1', #val OUT;