How to assign an exec result to a sql variable? - sql

How do you assign the result of an exec call to a variable in SQL? I have a stored proc called up_GetBusinessDay, which returns a single date.
Can you do something like this:
exec #PreviousBusinessDay = dbo.up_GetBusinessDay #Date, -1

I always use the return value to pass back error status. If you need to pass back one value I'd use an output parameter.
sample stored procedure, with an OUTPUT parameter:
CREATE PROCEDURE YourStoredProcedure
(
#Param1 int
,#Param2 varchar(5)
,#Param3 datetime OUTPUT
)
AS
IF ISNULL(#Param1,0)>5
BEGIN
SET #Param3=GETDATE()
END
ELSE
BEGIN
SET #Param3='1/1/2010'
END
RETURN 0
GO
call to the stored procedure, with an OUTPUT parameter:
DECLARE #OutputParameter datetime
,#ReturnValue int
EXEC #ReturnValue=YourStoredProcedure 1,null, #OutputParameter OUTPUT
PRINT #ReturnValue
PRINT CONVERT(char(23),#OutputParameter ,121)
OUTPUT:
0
2010-01-01 00:00:00.000

This will work if you wish to simply return an integer:
DECLARE #ResultForPos INT
EXEC #ResultForPos = storedprocedureName 'InputParameter'
SELECT #ResultForPos

declare #EventId int
CREATE TABLE #EventId (EventId int)
insert into #EventId exec rptInputEventId
set #EventId = (select * from #EventId)
drop table #EventId

From the documentation (assuming that you use SQL-Server):
USE AdventureWorks;
GO
DECLARE #returnstatus nvarchar(15);
SET #returnstatus = NULL;
EXEC #returnstatus = dbo.ufnGetSalesOrderStatusText #Status = 2;
PRINT #returnstatus;
GO
So yes, it should work that way.

I had the same question. While there are good answers here I decided to create a table-valued function. With a table (or scalar) valued function you don't have to change your stored proc. I simply did a select from the table-valued function. Note that the parameter (MyParameter is optional).
CREATE FUNCTION [dbo].[MyDateFunction]
(#MyParameter varchar(max))
RETURNS TABLE
AS
RETURN
(
--- Query your table or view or whatever and select the results.
SELECT DateValue FROM MyTable WHERE ID = #MyParameter;
)
To assign to your variable you simply can do something like:
Declare #MyDate datetime;
SET #MyDate = (SELECT DateValue FROM MyDateFunction(#MyParameter));
You can also use a scalar valued function:
CREATE FUNCTION TestDateFunction()
RETURNS datetime
BEGIN
RETURN (SELECT GetDate());
END
Then you can simply do
Declare #MyDate datetime;
SET #MyDate = (Select dbo.TestDateFunction());
SELECT #MyDate;

Here is solution for dynamic queries.
For example if you have more tables with different suffix:
dbo.SOMETHINGTABLE_ONE, dbo.SOMETHINGTABLE_TWO
Code:
DECLARE #INDEX AS NVARCHAR(20)
DECLARE #CheckVALUE AS NVARCHAR(max) = 'SELECT COUNT(SOMETHING) FROM
dbo.SOMETHINGTABLE_'+#INDEX+''
DECLARE #tempTable Table (TempVALUE int)
DECLARE #RESULTVAL INT
INSERT INTO #tempTable
EXEC sp_executesql #CheckVALUE
SET #RESULTVAL = (SELECT * FROM #tempTable)
DELETE #tempTable
SELECT #RESULTVAL

You can use a Table Variable for that
Code:
DECLARE #PreviousBusinessDay DATETIME
DECLARE #Temp TABLE(BusinessDay DATETIME)
INSERT INTO #Temp EXEC dbo.up_GetBusinessDay #Date, -1
SET #PreviousBusinessDay = (SELECT * FROM #Temp)
SELECT #PreviousBusinessDay
https://www.sqlservertutorial.net/sql-server-user-defined-functions/sql-server-table-variables/

Related

How can I return tables with different number of parameters with procedure?

I'm going to create different temp tables depending on the #selection parameter I get, and then I want to return the table I created.
I actually wanted to do it with the function, but I got an error for variable parameter tables. The sql procedur I wrote is as follows:
ALTER PROCEDURE [dbo].[Report]
(#Id BIGINT = 55,
#selection INT)
AS
BEGIN
IF #selection=1
BEGIN
Declare #tep_table table (Id int
,Name varchar(250)
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table
Select * from User
END
IF #selection=1
BEGIN
Declare #tep_table2 table (Id int
,CreateTime datetime
,UpdateTime datetime
,UpdatedBy varchar(250)
,Deleted bit
)
Insert into #tep_table2
Select * from Client
END
IF #selection=1
BEGIN
RETURN #tep_table
END
ELSE
BEGIN
RETURN #tep_table2
END
END
I am getting this error:
Must declare the scalar variable "#tep_table"
Personally I would turn this into three procedures to avoid the performance problems faced with multiple execution paths.
Something like this.
ALTER Procedure [dbo].[Report]
(
#Id bigint = 55 --not sure what the point of this parameter is as it wasn't used anywhere in the sample code
, #selection int
) AS
set nocount on;
IF #selection = 1
exec GetUserData;
IF #selection = 2
exec GetClientData;
GO
create procedure GetUserData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from [User];
GO
create procedure GetClientData
AS
set nocount on;
Select * --would prefer to use column names here instead of *
from Client;
GO

SQL Server: How to achieve re-usability yet flexibility in TSQL

I am using SQL Server 2008 R2. I am having some problems finding an effective coding pattern for SQL which supports code re-usability as well as flexibility. By re-usability, what I mean is keeping SQL queries in Stored Procedures and User Defined Functions.
Now, if I choose Stored Procedures, I will be sacrificing its usability in a query directly. If I choose User Defined Functions, I won't be able to use DML statements.
For example, suppose I created a Stored Procedures which inserts one contact record. Now, if I am having a table which can act as a source of multiple contact records, all I am left with are either WHILE loops or CURSORs, which is clearly not a recommended option, due to its performance drawbacks. And due to the fact that DML statements are not allowed in User Defined Functions, I simply cannot use them for this purpose.
Although, If I am not concerned with code re-usability, then instead of using Stored Procedures I can surely use same set of queries again and again to avoid while loops.
What pattern should I follow?
Here is a similar Stored Procedures:-
ALTER Proc [dbo].[InsertTranslationForCategory]
(
#str nvarchar(max),
#EventId int,
#CategoryName NVarchar(500),
#LanguageId int,
#DBCmdResponseCode Int Output,
#KeyIds nvarchar(max) Output
)as
BEGIN
DECLARE #XmlData XML
DECLARE #SystemCategoryId Int
DECLARE #CategoryId Int
Declare #Counter int=1
Declare #tempCount Int
Declare #IsExists int
Declare #TranslationToUpdate NVarchar(500)
Declare #EventName Varchar(200)
declare #Locale nvarchar(10)
declare #Code nvarchar(50)
declare #KeyName nvarchar(200)
declare #KeyValue nvarchar(500)
select #Locale=locale from languages where languageid = #LanguageId
SET #DBCmdResponseCode = 0
SET #KeyIds = ''
select #EventName = eventName from eventLanguages
where eventID = #EventId
--BEGIN TRY
Select #SystemCategoryId=CategoryId from SystemCategories where Name=rtrim(ltrim(#CategoryName))
Select #CategoryId=CategoryId from Categories where Name=rtrim(ltrim(#CategoryName)) and EventId=#EventId
if (#str='deactivate')
Begin
Delete from Codetranslation where CategoryId=#CategoryId
Update Categories set [Status]=0, Isfilter=0 where CategoryId=#CategoryId and Eventid=#EventId
Set #DBCmdResponseCode=2
return
End
set #XmlData=cast(#str as xml)
DECLARE #temp TABLE
(
Id int IDENTITY(1,1),
Code varchar(100),
Translation varchar(500),
CategoryId int
)
Insert into #temp (Code,Translation,CategoryId)
SELECT
tab.col.value('#Code', 'varchar(200)'),
tab.col.value('#Translation', 'varchar(500)'),#SystemCategoryId
FROM #XmlData.nodes('/Data') AS tab (col)
select #tempCount=Count(*) from #temp
if(IsNull(#CategoryId,0)>0)
Begin
While (#Counter <= #tempCount)
Begin
Select #IsExists= count(sc.categoryid) from #temp t Inner Join SystemCodetranslation sc
On sc.categoryid=t.CategoryId
where ltrim(rtrim(sc.code))=ltrim(rtrim(t.code)) and ltrim(rtrim(sc.ShortTranslation))=ltrim(rtrim(t.Translation))
and t.Id= #Counter
print #IsExists
Select #Code = Code , #KeyValue = Translation from #temp where id=#counter
set #KeyName = ltrim(rtrim(#EventName)) + '_' + ltrim(rtrim(#CategoryName)) + '_' + ltrim(rtrim(#Code)) + '_LT'
exec dbo.AddUpdateKeyValue #EventId,#Locale, #KeyName,#KeyValue,NULL,12
select #KeyIds = #KeyIds + convert(varchar(50),keyvalueId) + ',' from dbo.KeyValues
where eventid = #EventId and keyname = #KeyName and locale = #Locale
set #KeyName = ''
set #KeyValue = ''
Set #Counter= #Counter + 1
Set #IsExists=0
End
End
--- Inser data in Codetranslation table
if(isnull(#CategoryId,0)>0)
Begin
print #CategoryId
Delete from codetranslation where categoryid=#CategoryId
Insert into codetranslation (CategoryId,Code,LanguageId,ShortTranslation,LongTranslation,SortOrder)
SELECT
#CategoryId,
tab.col.value('#Code', 'varchar(200)'), #LanguageId,
tab.col.value('#Translation', 'varchar(500)'),
tab.col.value('#Translation', 'varchar(500)'),0
FROM #XmlData.nodes('/Data') AS tab (col)
Update Categories set [Status]=1 where CategoryId=#CategoryId and Eventid=#EventId
End
Set #DBCmdResponseCode=1
set #KeyIds = left(#KeyIds,len(#KeyIds)-1)
END
You can use table variable parameter for your user defined functions.
following code is an example of using table variable parameter in stored procedure.
CREATE TYPE IdList AS TABLE (Id INT)
CREATE PROCEDURE test
#Ids dbo.IdList READONLY
AS
Select *
From YourTable
Where YourTable.Id in (Select Id From #Ids)
End
GO
In order to execute your stored procedure use following format:
Declare #Ids dbo.IdList
Insert into #Ids(Id) values(1),(2),(3)
Execute dbo.test #Ids
Edit
In order to return Inserted Id, I don't use from Table Variable Parameter. I use following query sample for this purpose.
--CREATE TYPE NameList AS TABLE (Name NVarChar(100))
CREATE PROCEDURE test
#Names dbo.NameList READONLY
AS
Declare #T Table(Id Int)
Insert Into YourTable (Name)
OUTPUT Inserted.Id Into #T
Select Name
From #Names
Select * From #T
End
GO

Set variables from stored procedure from results of another stored procedure

How can I do something along the following lines?
DECLARE #Var1 VARCHAR(200)
DECLARE #Var2 VARCHAR(200)
SET #Var1 = value1 from sp_someotherprocedure(#id)
SET #Var2 = value1 from sp_someotherprocedure(#id)
I've created a simple example how to from results of stored procedure.
In order to set a variable to the return value from stored procedure you need to use
OUTPUT parameter with stored procedure, which will return the value.
CREATE PROCEDURE YourStoredProcedure
(
#i int,
#result int OUTPUT
)
AS
BEGIN
SET #i = 1
Set #result = #i + 10
return #result
END
-- Code to set the output paramter
DECLARE #outputparameter AS int
exec #outputparameter = YourStoredProcedure 10, #outputparameter output
print #outputparameter
Like this:
EXEC #Var1 = sp_someotherprocedure(#id)
Stored procedures could return many result sets. Therefore, it is not meant to be used with a SELECT.
They Could be used in a case where you have OUTPUT parameters
You should look into Functions and then SELECT from it.
CREATE FUNCTION SalesByStore (#storeid varchar(30))
RETURNS TABLE AS
RETURN (SELECT t.title, s.qty
FROM sales s
JOIN titles t ON t.title_id = s.title_id
WHERE s.stor_id = #storeid)
Then you call it like :
SELECT * FROM SalesByStore('6380')
I'm pretty late to the party on this one, but just ran into this issue myself. The solution my team and I came up with is to execute the result of the sproc into a temp table, then select top 1 (or whatever meets your criteria) into local variable(s). So using the OP's example might look something like this:
DECLARE #Var1 VARCHAR(200)
DECLARE #Var2 VARCHAR(200)
DECLARE #sprocResult TABLE(val1 INT, val2 INT)
INSERT INTO #sprocResult (val1, val2)
EXEC sp_someotherprocedure #id
SELECT TOP 1
#Var1 = val1,
#Var2 = val2
FROM #sprocResult

How to return the output of stored procedure into a variable in sql server

I want to execute a stored procedure in SQL Server and assign the output to a variable (it returns a single value) ?
That depends on the nature of the information you want to return.
If it is a single integer value, you can use the return statement
create proc myproc
as
begin
return 1
end
go
declare #i int
exec #i = myproc
If you have a non integer value, or a number of scalar values, you can use output parameters
create proc myproc
#a int output,
#b varchar(50) output
as
begin
select #a = 1, #b='hello'
end
go
declare #i int, #j varchar(50)
exec myproc #i output, #j output
If you want to return a dataset, you can use insert exec
create proc myproc
as
begin
select name from sysobjects
end
go
declare #t table (name varchar(100))
insert #t (name)
exec myproc
You can even return a cursor but that's just horrid so I shan't give an example :)
You can use the return statement inside a stored procedure to return an integer status code (and only of integer type). By convention a return value of zero is used for success.
If no return is explicitly set, then the stored procedure returns zero.
CREATE PROCEDURE GetImmediateManager
#employeeID INT,
#managerID INT OUTPUT
AS
BEGIN
SELECT #managerID = ManagerID
FROM HumanResources.Employee
WHERE EmployeeID = #employeeID
if ##rowcount = 0 -- manager not found?
return 1;
END
And you call it this way:
DECLARE #return_status int;
DECLARE #managerID int;
EXEC #return_status = GetImmediateManager 2, #managerID output;
if #return_status = 1
print N'Immediate manager not found!';
else
print N'ManagerID is ' + #managerID;
go
You should use the return value for status codes only. To return data, you should use output parameters.
If you want to return a dataset, then use an output parameter of type cursor.
more on RETURN statement
Use this code, Working properly
CREATE PROCEDURE [dbo].[sp_delete_item]
#ItemId int = 0
#status bit OUT
AS
Begin
DECLARE #cnt int;
DECLARE #status int =0;
SET NOCOUNT OFF
SELECT #cnt =COUNT(Id) from ItemTransaction where ItemId = #ItemId
if(#cnt = 1)
Begin
return #status;
End
else
Begin
SET #status =1;
return #status;
End
END
Execute SP
DECLARE #statuss bit;
EXECUTE [dbo].[sp_delete_item] 6, #statuss output;
PRINT #statuss;
With the Return statement from the proc, I needed to assign the temp variable and pass it to another stored procedure. The value was getting assigned fine but when passing it as a parameter, it lost the value. I had to create a temp table and set the variable from the table (SQL 2008)
From this:
declare #anID int
exec #anID = dbo.StoredProc_Fetch #ID, #anotherID, #finalID
exec dbo.ADifferentStoredProc #anID (no value here)
To this:
declare #t table(id int)
declare #anID int
insert into #t exec dbo.StoredProc_Fetch #ID, #anotherID, #finalID
set #anID= (select Top 1 * from #t)

Assign a variable to the output of a stored procedure

I am trying to assign the output of a stored procedure to a variable using T-SQL
I have a stored procedure that I pass a varbinary(128) variable and it decrypts it using a key and has an output variable for the decrypted value. I'm not sure if my syntax is correct because when I run the procedure it gives the correct result but when I assign to a variable, then select the variable it is always null
declare #e as varbinary(128)
set #e = *encrypted value*
declare #t as int
set #t = 0
exec *storedprocedure* #data = #e,#t output
select #t
t is null when I select above
Here is a simple example
CREATE PROC myProc #in INT, #out INT OUTPUT
AS
SELECT #out = #in+20
GO
DECLARE #in INT, #out INT
SET #in = 1
EXEC myProc #in= #in, #out=#out OUTPUT
SELECT #out
DROP PROC myProc