I'm getting different result for outputParam from fallowing two queries. The first one is generated by entity framework and it gives 0 for outputParam. For the second result is 5.
declare #p2 int
set #p2=0
exec sp_executesql N'usp_GetOrders #order_date, #output_param',N'#order_date datetime,#output_param int output',#order_date='2015-05-07 12:37:14.579',#output_param=#p2 output
select #p2 AS outputParam
declare #p2 int
set #p2=0
exec [dbo].[usp_GetOrders] #order_date='2015-05-07 12:37:14.579',#output_param=#p2 output
select #p2 AS outputParam
Procedure looks like this
CREATE PROCEDURE [dbo].[usp_GetOrders]
#order_date AS datetime,
#output_param AS int OUTPUT
AS
BEGIN
SELECT #output_param=5
SELECT o.Id
FROM dbo.[Order] o
WHERE OrderDate > #order_date
END
The reason is because you are missing output when calling the procedure using sp_executesql.
exec sp_executesql N'usp_GetOrders #order_date, #output_param output',N'#order_date datetime,#output_param int output',#order_date='2015-05-07 12:37:14.579',#output_param=#p2 output
Your direct procedure call is correct, what is why it is returning the correct value. If you call your procedure without output, it will return 0 as well.
exec [dbo].[usp_GetOrders] #order_date='2015-05-07 12:37:14.579',#output_param=#p2
Related
I've created a procedure that has 2 input params and 1 output. I return the output at the end of the batch, now I want to exec the procedure but it won't because it says it expects a parameter of #TotPayroll
however I expect an output with nothing to input.
USE PR
GO
CREATE PROC spPayroll
#TotPayroll money OUTPUT,
#StartDate smalldatetime = NULL,
#EndDate smalldatetime = NULL
AS
IF #StartDate IS NULL AND #EndDate IS NULL
BEGIN
SELECT #StartDate = MIN(PerFrom) FROM vwPayCalc;
SELECT #EndDate = MAX(PerFrom) FROM vwPayCalc;
END
SELECT #TotPayroll = SUM(GrossPay)
FROM vwPayCalc
WHERE PerFrom >= #StartDate AND PerFrom <= #EndDate
RETURN #TotPayroll;
GO
EXEC spPayroll
It's an output parameter. You still have to supply a variable for the value to be written into1:
declare #payroll money
exec spPayroll #payroll OUTPUT
--do something with #payroll
I return the output at the end of the batch
There's no need to do that. And in many cases trying to do so would cause an error. Stored procedures have a return value that must always be an int. That's what the value supplied to return sets. If you're lucky, your supplied value can be converted to int. If you're unlucky, you get a conversion error.
The return value would usually be used if you're using an "error code" convention for indicating errors back to your caller.
1Yes, you have to mark it as OUTPUT when calling too. Omit the OUTPUT here and the code will run but your variable's value will not be set.
Return Data from a Stored Procedure
There are three ways of returning data from a procedure to a calling program: result sets, output parameters, and return codes.
I think the first way could meet your case, you can see the sample code as below
create proc spPayroll
#s date = null,
#e date = null
as
declare #r decimal(18,2)
set #r = 18333.11
select #r
exec spPayroll
--18333.11
for more detail information you could find it on the official website https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/return-data-from-a-stored-procedure?view=sql-server-ver15#examples-of-cursor-output-parameters
I've created a procedure that has 2 input params and 1 output.
The procedure has 3 input parameters, one of them is also output:
create procedure testABC
#p1 int = 10,
#p2 int = 0 output,
#p3 int = 5
as
begin
select #p1+#p2+#p3 as input_total;
select #p2 = 1234; -- output 1234
end
go
exec dbo.testABC;
exec dbo.testABC #p2 = 1000; --#p2 is also output;
go
declare #myp2 int = 500;
exec dbo.testABC #p2 = #myp2 output;
select #myp2 as myp2outputfromproc;
go
drop procedure testABC;
I am trying to hands on with TSQLT unittest framework for first time and have come across a problem. I have a stored proc like this which returns some numbers
Use Mydatabase
Declare #parameter1, #parameter2,#paramter3
BEGIN
SELECT #parameter1 = dbo.[function](#paramter2,parameter3)
..
..
-- Now some Dynamic SQL joins on two tables
BEGIN
SET #SQL = 'SELECT COLUMN1, COLUMN2 FROM FROM TABLE1 INNER JOIN TABLE2 ON TABLE1.COLUMN1 =
TABLE2.COLUMN2 WHERE TABLE2.COLUMN3 = + CAST(#parameter1 as varchar(10))
EXECUTE sp_executesql #SQL, Output parameter
return
The problem is the table1 and table2 are updated daily and I can't assert to values that are changing so I came across fake tables and spy procedures,
Is there a way to utilize the spyprocedures to use the faketables rather than original tables.?
Since my actual db and Unit test db are different but with in same connection, how can I reference the actual to the test one as I am getting error as
Cannot use SpyProcedure on [WD0000\server].[database].[dbo].[usp.mystoredproc] because the procedure does not exist
TSQLT code
EXEC tSQLt.NewTestClass 'SegmentSizeTest'
GO
CREATE PROCEDURE SegmentSizeTest.[test that checks the segment size]
AS
BEGIN
DECLARE #return_value int,#TotalCount int,#OneCount int,#TwoCount int
declare #Criteria Varchar(MAX)
declare #rampUpFactor int
declare #expected int
declare #actual int
SET #Criteria = 'My Criteria'
SET #GeoflexCriteria = NULL
--#TotalCount = #TotalCount OUTPUT
--#OneCount = #OneCount OUTPUT
-- #TwoCount = #TwoCount OUTPUT
SET #rampUpFactor = 1
set #expected = 160486
------Fake Table
EXEC tSQLt.FakeTable 'UnitTest.Household';
EXEC tSQLT.FakeTable 'UnitTest.Customer';
--
..Insert to UnitTest.Household and UnitTest.Customer tables
------Execution
EXEC #return_value = [VAReportingDB].[dbo].[GetSegmentSize]
#Criteria = #Criteria,
#TotalCount = #TotalCount OUTPUT,
#OneCount = #OneCount OUTPUT,
#TwoCount = #TwoCount OUTPUT
SELECT #TotalCount as N'#TotalCount',
#OneCount as N'#OneCount',
#TwoCount as N'#TwoCount'
------Assertion
EXEC tSQLt.AssertEquals #expected, #TotalCount;
END;
GO
FakeTable replaces the original table wit a test double. Therefore any code that is written to access the original table, dynamically or otherwise, will “see” the faked table during a test.
Independently, you should pass in #parameter1 to sp_executesql instead of concatenating it into your Sql statement. At least if your original code is similar to what you posted here.
I have this stored procedure:
create proc Sponsors.GetLightBoxAd
(
#SponsorID varchar(30),
#ADIDOut varchar(30) OUTPUT,
#UserID varchar(30),
#ProjectID varchar(50),
#PlatformID int
)
as
begin
SELECT TOP 1 #ADIDOut = AD.ADID --my output. AD.ADID is a varchar(30) column
FROM Sponsors.AD
WHERE AD.Active = 1 and AD.SponsorID = #SponsorID
ORDER by NEWID() -- I want the first one picked at random
IF ISNULL(#ADIDOut,-1) != -1 --if the result set wasn't null, run some update queries with the result
BEGIN --These queries do not have output variables.
EXEC Sponsors.proc1 #ADIDOut, #SponsorID
EXEC Projects.proc2 #ProjectID,#ADIDOut,#UserID,#PlatformID
END --end the if
end --end the proc
go
This should return either a null value or a varchar.
However when I try to execute the query, SSMS auto-generates this code for me to run the query:
USE [MyDB]
GO
DECLARE #return_value int, --Why is this here???
#ADIDOut varchar(30) -- this should be my only output
EXEC #return_value = [Sponsors].[GetLightBoxAd]
#SponsorID = N'Alienware',
#ADIDOut = #ADIDOut OUTPUT,
#UserID = N'127.0.0.1',
#ProjectID = N'TestProject',
#PlatformID = 1
SELECT #ADIDOut as N'#ADIDOut'
SELECT 'Return Value' = #return_value --why is this here?
GO
And then it gives me an error because it appears to try to convert the result of ADIDOut into an int... Why is there an int #Return_Value variable and why is it trying to put my actual OUTPUT result into it?
The error was in this line:
IF ISNULL(#ADIDOut,-1) != -1
It seems since I put just -1 without quotes as the comparison, sql reads this as an integer and cannot compare it to a nullable string so the error is raised. Putting the -1's into quotes fixes the error and the query runs. Thanks for the help!
I have a stored procedure like this:
create proc calcaulateavaerage
#studentid int
as
begin
-- some complicated business and query
return #result -- single decimal value
end
and then I want to
create proc the whole result
select * , ................................ from X where X.value > (calculateaverage X.Id)
It always gives an error that reads like "multi-part identifier calculateaverage couldn't be bound." Any idea how to solve that?
You don't want a stored procedure. You want a function.
Use Output variables to output the data out of stored procedure:
create proc calcaulateavaerage
#studentid int, #result int
as
begin
-- some complecated business and query
select #result = id from sometable;
end
-- Declaring output variable named result;
declare #result int;
-- Passing output variable to stored procedure.
exec calculateaverage 1, #result;
-- Now you can display the result or do whatever you like.
print #result
How use output parameter from procedure?
Assuming that you have a sproc with an output parameter. You can call it and read the output value.
CREATE PROCEDURE AddOne
#val int,
#valPlusOne int out
AS
BEGIN
SET NOCOUNT ON;
SET #valPlusOne = #val + 1
END
GO
--This is used to store the output
declare #PlusOne int
--This calls the stored procedure setting the output parameter
exec AddOne 1, #valPlusOne=#PlusOne OUT
--This displays the value of the output param
select #Plusone