Get first row, first column value from stored procedure - sql

I am calling a stored procedure (that I can't modify) that returns a single value via a SELECT at the end of the procedure. I need to use that value in my own procedure. How can I get that value?
Here is an example of the procedure I am calling that I can not modify:
CREATE PROCEDURE [dbo].[SP_poorlywritten] (
....
)
BEGIN
....
SELECT #lastkey;
RETURN (0);
END
And here is what I am trying to do, but it doesn't work because this gets the return value, and what I need is that SELECT value:
exec #next_key = SP_poorlywritten 'tablename',1;
How can I store the first column, first row value from a store procedure?

If you cannot modify the existing stored procedure, you will not be able to utilize the RETURN as you would like to.
An alternative may be to insert the output of the procedure's select statement into a temp table, and then query that directly to populate a variable.
That would look like this.
CREATE TABLE #tmp
(
LastKey INT
)
INSERT INTO #tmp
EXEC [dbo].[SP_poorlywritten]
See this existing post for more details on how you might accomplish this.
As Aaron Bertrand pointed out, RETURN is for error/status. If you were able to modify the stored procedure, you would want to utilize an output parameter instead of RETURN. This is how you would do that.
CREATE PROCEDURE proc_name
#Output int OUTPUT
AS
<do some stuff>
SET #Output = <some_value>
GO
DECLARE #Output int
EXEC proc_name #Output = #Output

Related

Why would a stored procedure return a 0 and the selected id?

I have a stored procedure like this:
CREATE PROCEDURE [dbo].[create_myNewId]
(#parentId BIGINT)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [Mapping] (ParentId)
VALUES (#parentId)
SELECT SCOPE_IDENTITY();
END
This, when run on its own, returns the new id that has been assigned to the new row that's inserted with the parent id. However, when I do something like this:
DECLARE #NewId int
EXEC #NewId = create_myNewId #parentId = 33333
SELECT #NewId
When running this, the output window shows the result of the stored procedure, which returns an Id but #NewId always is 0. I fixed this by changing the stored procedure to use RETURN SCOPE_IDENTITY() but I was wondering why SELECT didn't work in this case?
I have my suspicions that it's something around the 0 being the success status being returned first from the stored procedure rather than the result, but was curious why this doesn't then happen when called directly from the client.
No! Write the procedure the right way:
CREATE PROCEDURE [dbo].[create_myNewId] (
#parentId bigint,
#outId bigint OUTPUT
) AS
BEGIN
SET NOCOUNT ON;
DECLARE #ids TABLE (id bigint);
INSERT INTO [Mapping](ParentId)
OUTPUT id INTO #ids
VALUES (#parentId);
SELECT #outId = id
FROM #ids;
END;
Then call this as:
DECLARE #NewId int;
EXEC create_myNewId #parentId = 33333, #NewId OUTPUT;
SELECT #NewId;
The OUTPUT clause is the recommend way to get results from a data-modification clause. The older methods using the *_IDENTITY() functions should be obsoleted.
Stored procedures do return values. These are integers that are designed to return status information. Other information should be returned via OUTPUT parameters.
Microsoft's design intent for stored procedures is that they always return an int to describe how successful the process undertaken by the procedure was. It's not intended to return a result data, and you're free to define the bits you want to return to describe succes, partial success etc. You could abuse it to return an integer result data (count query for example) if you wanted, but it's not the design intention
Executing a select query within a stored procedure creates a result set you can read on your client if the sproc is the kind that is intended to return data
My suggestion is to use an OUTPUT parameter. Not only will it be 'easier' to use when calling the stored procedure, it will also be clearer to the person calling the stored procedure.
CREATE PROCEDURE [dbo].[create_myNewId]
(#parentId BIGINT,
#myNewId BIGINT OUTPUT)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [Mapping] ([ParentId])
VALUES (#parentId);
SET #myNewId = SCOPE_IDENTITY();
END;
GO
You would then call your stored procedure like this:
DECLARE #myNewId BIGINT;
EXECUTE [dbo].[create_myNewId] #parentId = 0, -- bigint
#myNewId = #myNewId OUTPUT; -- bigint
SELECT [This was just inserted] = #myNewId;
For anyone who has 0 as return value from a stored procedure, check if the stored procedure executes from the right database and only one procedure exists within the given context. Output parameters wouldn't be of any use if you ever plan to access the DB with ORM and the procedure returns an object's property.

How to use a variable from one stored procedure in a different stored procedure (SQL)

I have written a stored procedure as follows (this is a simplified version - the SP does a lot of other things but these are the key parts):
CREATE PROCEDURE [dbo].[_uspCustomSP]
AS
BEGIN
CREATE TABLE #custno(custno int)
INSERT INTO #custno
EXEC usp_GetCustomerNo
DECLARE #custnumber nvarchar(5)
SET #custnumber = (SELECT custno FROM #custno)
DROP TABLE #custno-- drop table so fresh each time
END
This SP works as I want it to. However, I want to be able to refer to the value of #custnumber in a different stored procedure. Is there any way of persisting the value of #custnumber but without rerunning usp_GetCustomerNo (as every time it is run, the value of #custnumber changes - I want to be able to use the exact number as stored in the variable.)
EDIT: I've had a really helpful response below suggesting I include an output parameters. I have thought about this but I'm not sure how to refer to this output elsewhere (in a different SP) without re-running the entire SP at the same time.
Apologies if I've not included enough information.
Many thanks,
Helen
You can have the stored procedure return the value:
CREATE PROCEDURE [dbo].[_uspCustomSP] (
#custnumber nvarchar(5) OUTPUT
) AS
BEGIN
CREATE TABLE #custno(custno int) ;
INSERT INTO #custno (custno)
EXEC usp_GetCustomerNo;
SELECT #custnumber = custno FROM #custno ;
DROP TABLE #custno-- drop table so fresh each time
END;
Having said that, I have some comments on the stored procedure:
There is no need to drop the temporary table. I prefer table variables, because it is obvious they go out of scope.
I think it is dangerous to return a single value in a table. Why not use a scalar function or OUTPUT parameter for usp_GetCustomerNo?
You should get in the habit of putting semicolons at the end of statements and always using a column list with INSERT.
You would call the stored procedure as:
declare #custnumber nvarchar(5);
exec sp_executesql _uspCustomSP,
N'#custnumber nvarchar(5) output',
#custnumber=#custnumber output;

SQL return the output of SELECT and not the output of another stored procedure

How do I return the result of the SELECT as the output of the stored procedure? Sorry I'm new to stored procedures!
In this query below I'm calling stored procedure spCuExt_ExtractLog and assigning the result to variable #StartDate. I then use this variable within the main stored procedure, in a SELECT statement. I need to return only the result of the SELECT statement from the main stored procedure:
-- Main stored procedure
BEGIN
DECLARE #StartDate DATETIME
EXEC #StartDate = spCuExt_ExtractLog 'Customers'
SELECT Id, [Name], LogoPath, IsDeleted
FROM dbo.Customers
WHERE RecordCreatedDateUTC>= #StartDate
END
This returns the result of the call to spCuExt_ExtractLog as well as the result of the SELECT statement but I want to output the result of the SELECT only.
How do I do this?
Put the results into a table variable instead:
create procedure dbo.usp_Child
as
begin
select N'Hello world!' as [message];
end;
go
create procedure dbo.usp_Main
as
begin;
declare #results table ([message] nvarchar(max));
insert into #results
execute dbo.usp_Child;
select N'success';
end;
go
execute dbo.usp_Main;
Here's a link to a pretty good document explaining all the different ways to solve your problem (although a lot of them can't be used since you can't modify the existing stored procedure.)
http://www.sommarskog.se/share_data.html

Parsing returned value from stored procedure into table/variable

I have stored procedure, which uses couple of functions, and those functions are comparing some data.
For example:
function one:
if #x is not null
begin
if #x > #y
return 'y cannot be less than x'
and on stored procedure I declare some variables which are our Xs and Ys.
Then I starting new transaction, for example:
begin tran test;
exec [dbo].[My_stored_procedure] # stored prodecure which using function I wrote above.
'some_value','some_value' # our X and Y
rollback test;
and everything works correctly, when condition from function (x > y) is met, then we can see returned message "'y cannot be less than x'". And I want that message, to be saved in variable or table, but without editing stored procedure/function. I tried something like that:
begin tran test;
CREATE TABLE stored_test
(
result nvarchar(2000)
)
INSERT INTO stored_test(result) exec [dbo].[My_stored_procedure]
'some_value','some_value'
rollback test;
And it works, but "result" is emtpy. And I want it to contain return message from function, which are used in stored procedure.
You have to modify the stored procedure to get any return value from it. You need to declare an output variable in the stored procedure and then store that message in the variable, and at the last call procedure like:
EXECUTE Sales.uspGetEmployeeSalesYTD #SalesYTD = #SalesYTDBySalesPerson OUTPUT

What is the best way to assign the returned value of a stored proc to a variable in SQL?

I have a stored procedure that returns a valueI call it from other stored procedures that need to retrieve this value. The calling stored procedure is inside a transaction, the stored procedure that returns the value (and actually creates the value and stores it in a table that no other proc touches) is not inside its own transaction, but would be part of the caller's transaction.
The question is this, what is the most efficient way of retrieving the return value of the stored procedure and storing it in a variable in the calling proc?
Currently I have the following and I'm wondering if its very inefficient?
DECLARE #tmpNewValue TABLE (newvalue int)
INSERT INTO #tmpNewValue EXEC GetMyValue
DECLARE #localVariable int
SET #localVariable = (SELECT TOP 1 newvalue FROM #tmpNewValue )
Isn't there a more straight forward way of doing this? Isn't this an expensive (in terms of performance) way?
My stored proc doesn't have an output param, it just returns a value. Would using an output param be faster?
For what it's worth I'm using MS SQL Server 2005
If your getting a single return variable then yes this is innefficent you can do:
declare #localVariable int
exec #localVariable =GetMyValue
select #localVariable
See How to Share Data Between Stored Procedures
By some reasons 'exec #localVariable =GetMyValue' is not working for me (MS SQL 2005), it's always return 0 value (They have the same issue).
My opinion is:
if you can change stored procedure, add output parameter.
else if you can remove procedure, rewrite it as a function.
else use table variable, as you do.
Is this proc returning a rowset of 1 row and 1 column or no rowset at all and you just want to capture the returncode?
If you want just the returncode then use Josh's method otherwise use a OUTPUT parameter sicne it will be much faster than what you are doing now
To Explain what I mean run this code
use tempdb
go
create proc GetMyValue
as
select 1
go
create table #temp (id int)
declare #localVariable int
insert #temp
exec #localVariable =GetMyValue
select #localVariable,* from #temp
Try this:
create proc AvilableSeats
as
declare #v1 int,#v2 int
exec #v1= determinPath_Capacity 1,'Sat-Tue',32
exec #v2=Student_fGroup '6/12/2009'
select #v1-#v2