Procedure call inside procedure - sql

First I need to check if spOBJ_CopyInspectiontask has any errors, if there are no errors, only then proceed to the insert statement.
DECLARE #tblSystemId TABLE
(
OldSysId int, NewSysId int,
OldTaskId int, NewTaskId int,
TaskObjectIds varchar(max) null
);
INSERT INTO #tblSystemId (OldSysId , NewSysId, OldTaskId, NewTaskId, TaskObjectIds)
EXEC dbo.spOBJ_CopyInspectiontask #UserId, #TargetCustomerId, #TargetContractId, #TargetSiteId, #SourceCustomerId, #OldTaskId, #SystemName, #Checkall, #CopyReports, #Return OUTPUT, #ObjectIds OUTPUT;
How can I check that?

Perhaps you want a try/catch block:
BEGIN TRY
INSERT INTO #tblSystemId (OldSysId , NewSysId, OldTaskId, NewTaskId,TaskObjectIds )
EXEC dbo.spOBJ_CopyInspectiontask #UserId,#TargetCustomerId, #TargetContractId, #TargetSiteId,
#SourceCustomerId, #OldTaskId, #SystemName, #Checkall, #CopyReports, #Return OUTPUT, #ObjectIds OUTPUT;
END TRY
BEGIN CATCH
-- do something here in the event of failure
END CATCH;

Related

How to return an id and use it directly in another stored procedure?

I want his stored procedure to return the inserted id
ALTER PROCEDURE [dbo].[InsertAddress_DBO]
#Name VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[Address]([Address_Name])
OUTPUT INSERTED.Address_Id
VALUES (#Name)
END
This one the same
ALTER PROCEDURE [dbo].[InsertDocumentation_DBO]
#Texte VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[Documentation]([Documentation_Text])
OUTPUT inserted.Documentation_Id
VALUES (#Texte)
END
And this one to use them and return her own -
like using the inserted id to put it into the next stored procedure as a parameter
ALTER PROCEDURE [dbo].[InsertEstablishmentByStrings_DBO]
#Establishment_Name VARCHAR(50),
#Address_Name VARCHAR(50),
#Documentation_Text VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Address_ID INT ,
#Documentation_ID INT
EXEC #Address_ID = [dbo].[InsertAddress_DBO]
#Name = "rue de la banchiesserie 85 Golback"
EXEC #Documentation_ID = [dbo].[InsertDocumentation_DBO]
#Texte = "né en 55555 restaurant fabuleux"
INSERT INTO [dbo].[Establishment]([Establishment_Name],[Address_Id],[Documentation_Id])
OUTPUT inserted.Establishment_Id
VALUES (#Establishment_Name,#Address_ID,#Documentation_ID)
END
However, I always get an error, because the stored procedure doesn't return the id when I execute it.
What is wrong in my code?
I would like to get the code I could use again and again in each stored procedure I have to execute. I already tried ##Identity, indent, scoped,... nothing works.
If you want to return something from stored procedure to the context of SQL query execution you may use a return statement or an output parameter. I would suggest you to use the second option. The first one is generally intended to return status of procedure execution.
ALTER PROCEDURE [dbo].[InsertAddress_DBO]
#Name VARCHAR(50),
#Address_ID INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[Address]([Address_Name])
VALUES (#Name)
SET #Address_ID = SCOPE_IDENTITY()
END
Than you can use returned value in your outer procedure
ALTER PROCEDURE [dbo].[InsertEstablishmentByStrings_DBO]
#Establishment_Name VARCHAR(50),
#Address_Name VARCHAR(50),
#Documentation_Text VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Address_ID INT ,
#Documentation_ID INT
EXEC [dbo].[InsertAddress_DBO]
#Address_ID = #Address_ID OUTPUT,
#Name = "rue de la banchiesserie 85 Golback"
...
END
An OUTPUT INSERTED clause you used doesn't returns data to the query execution context but send them to the output stream.
Your stored procedures should look like this, using an OUTPUT parameter, not trying to consume a RETURN value (which should never contain data) using a resultset. Also [don't] [put] [everything] [in] [square] [brackets] [unless] [you] [have] [to], [because] [all] [it] [does] [is] [hamper] [readability], and don't surround string literals with "double quotes" because that means something else in T-SQL.
CREATE OR ALTER PROCEDURE dbo.InsertAddress_DBO
#Name varchar(50),
#Address_Id int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.Address(Address_Name)
VALUES (#Name);
SELECT #Address_Id = SCOPE_IDENTITY();
END
GO
CREATE OR ALTER PROCEDURE dbo.InsertDocumentation_DBO
#Texte varchar(50),
#Doc_Id int OUTPUT
AS
BEGIN
SET NOCOUNT ON;
INSERT dbo.Documentation(Documentation_Text)
VALUES (#Texte);
SELECT #Doc_Id = SCOPE_IDENTITY();
END
GO
Now, your main procedure can do this:
CREATE OR ALTER PROCEDURE dbo.InsertEstablishmentByStrings_DBO
#Establishment_Name varchar(50),
#Address_Name varchar(50),
#Documentation_Text varchar(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Address_ID INT ,
#Documentation_ID INT
EXEC dbo.InsertAddress_DBO
#Name = #Address_Name,
#Address_Id = #Address_ID OUTPUT;
EXEC dbo.InsertDocumentation_DBO
#Texte = Documentation_Text,
#Doc_Id = #Documentation_ID OUTPUT;
INSERT dbo.Establishment
(Establishment_Name, Address_Id, Documentation_Id)
OUTPUT inserted.Establishment_Id,
inserted.Address_ID, inserted.Documentation_ID
VALUES (#Establishment_Name,#Address_ID,#Documentation_ID);
END
GO
And you call it like this:
EXEC dbo.InsertEstablishmentByStrings_DBO
#Establishment_Name = 'Gaston''s',
#Address_Name = 'rue de la banchiesserie 85 Golback',
#Documentation_Text = 'né en 55555 restaurant fabuleux';
And get results like this:
Establishment_Id
Address_ID
Documentation_ID
1
1
1
Fully working example on db<>fiddle

Set variable with Scope Identity after executing different stored proc

I am trying to set a declared variable in a stored procedure after making use of another stored procedure to INSERT a 'Case' first.
The pseudo code looks like this:
DECLARE #CaseId variable
INSERT Case into Case table
SET #CaseId using SCOPE_IDENTITY
IF Case.CaseID = #CaseId
--rest of script
The below script works as expected for me:
INSERT INTO Case (CaseRef, [Source], DateCreated, CaseType)
VALUES (#caseRef, #source, #dateCreated, #caseType)
SET #caseID = SCOPE_IDENTITY();
I've tried with the below script but it doesn't seem to set the variable. Is this possible? Or must I set it the way I'm doing in the above script?
EXEC sp_InsertCase #caseRef, #source, #dateCreated, #caseType
SET #caseID = SCOPE_IDENTITY();
scope_identity() does what it says on the tin - it gives you the last identity value generated in the current scope. A stored procedure defines a scope. So when the stored procedure that causes the identity value to be generated exits, you're no longer in the scope where the value was generated, so scope_identity() can't tell you anything.
What you can do is capture the scope_identity() value into a variable inside the stored procedure, and return it as an output parameter:
create table t(i int identity(1,1), j int);
go
create proc insert_and_get_scope #scopeid int = null output as
begin
insert t(j) values (1);
set #scopeid = scope_identity();
end
go
declare #scopeid int;
exec insert_and_get_scope #scopeid output;
select #scopeid;
You can see from the example below:
DROP TABLE IF EXISTS [dbo].[StackOverflow];
CREATE TABLE [dbo].[StackOverflow]
(
[RowID] INT IDENTITY(1,1) NOT NULL
);
GO
CREATE OR ALTER PROCEDURE [dbo].[sp_StackOverflow]
AS
BEGIN;
INSERT INTO [dbo].[StackOverflow]
DEFAULT VALUES;
END;
GO
EXEC [dbo].[sp_StackOverflow];
SELECT SCOPE_IDENTITY();
it is not working, because it is not in the current scope:
Returns the last identity value inserted into an identity column in
the same scope. A scope is a module: a stored procedure, trigger,
function, or batch. Therefore, if two statements are in the same
stored procedure, function, or batch, they are in the same scope.
but you can try this:
DROP TABLE IF EXISTS [dbo].[StackOverflow];
CREATE TABLE [dbo].[StackOverflow]
(
[RowID] INT IDENTITY(1,1) NOT NULL
);
GO
CREATE OR ALTER PROCEDURE [dbo].[sp_StackOverflow]
(
#RowID BIGINT OUTPUT
)
AS
BEGIN;
INSERT INTO [dbo].[StackOverflow]
DEFAULT VALUES;
SET #RowID = SCOPE_IDENTITY()
END;
GO
DECLARE #RowID BIGINT;
EXEC [dbo].[sp_StackOverflow] #RowID = #RowID OUTPUT;
SELECT #RowID;

how to pass parameter that I get from one Stored Procedure to another Stored Procedure?

I need to execute stored procedure that his ID will be the execute of another stored procedure. how can I do this?
ALTER PROCEDURE [dbo].[spABC]
#ID INT
,#TypeString nvarchar(50)
AS
BEGIN
--exec SECOND_SP
INSERT INTO dbo.abc (Id, TypeString)
VALUES (#"result from the second sp.", #TypeString)
END
As Gordon wrote in the comments, You could have an output parameter on the second stored procedure. another option would be to use rahul's example (if the second stored procedure simply returns a scalar value)
here is a quick example:
CREATE PROCEDURE Second_SP
(
#InParam varchar(10),
#OutParam int OUTPUT -- note the OUTPUT directive
)
AS
-- do stored procedure stuff here
-- set a value to the output parameter:
SET #OutParam = 1234
GO
in the first stored procedure you should use the output directive when executing the second procedure:
ALTER PROCEDURE [dbo].[spABC]
#ID INT
,#TypeString nvarchar(50)
AS
BEGIN
DECLARE #InParam varchar(10),
#OutParam int
-- set parameters values before executing...
exec SECOND_SP #InParam, #OutParam OUTPUT -- note the output directive
INSERT INTO dbo.abc (Id, TypeString)
VALUES (#OutParam, #TypeString)
END
Not sure why all the down votes on the question. English may be a little weak, but stored procedure parameters are arcane.
You must define the procedure AND the EXEC as passing the parameter and expecting OUTPUT. Stored procedure can include a RETURN, but I am pretty sure that value is always an INTEGER, and OP wants a string.
For example:
BEGIN TRANSACTION
GO
CREATE PROCEDURE dbo.SECOND_SP (#ID INT, #Type VARCHAR(9) OUTPUT)
AS
-- totally arbitrary, pretend logic for second sp for illustrative purposes
SET #Type = CASE WHEN #ID > 90000 THEN 'ADMIN'
WHEN #ID > 9000 THEN 'MANAGER' ELSE 'USER' END
GO
CREATE PROCEDURE [dbo].[spABC]
#ID INT
AS
BEGIN
DECLARE #TypeString VARCHAR(9)
exec SECOND_SP #ID, #Type = #TypeString OUTPUT
SELECT #ID, #TypeString
-- INSERT INTO dbo.abc (Id, TypeString) VALUES (#"result from the second sp.", #TypeString)
END
GO
--TEST IT .....
EXEC [dbo].[spABC] 1111
EXEC [dbo].[spABC] 9123
EXEC [dbo].[spABC] 99543
ROLLBACK
--- RESULTS:
1111 USER
----------- ---------
9123 MANAGER
----------- ---------
99543 ADMIN
If you cannot update SECOND_SP to return the value as an OUTPUT parameter, and that stored procedure returns a single row, you can insert that into a Temporary Table (i.e. #Table) or a Table Variable (i.e. #Table) and then get the value from that table. Something along the lines of:
DECLARE #TempProcResult TABLE (ID INT, OtherField VARCHAR(50));
INSERT INTO #TempProcResult (ID, OtherField)
EXEC SECOND_SP #ID;
INSERT INTO dbo.abc (Id, TypeString)
SELECT tmp.ID, #TypeString
FROM #TempProcResult tmp;
Per your post, Considering that your second procedure SECOND_SP needs the #ID parameter and you want to have the return value of second procedure to the INSERT statement. you can do that like
ALTER PROCEDURE [dbo].[spABC]
#ID INT
,#TypeString nvarchar(50)
AS
BEGIN
declare #var int;
exec #var = SECOND_SP #ID;
INSERT INTO dbo.abc (Id, TypeString)
VALUES (#var, #TypeString)
END
EDIT:
Per comment from #srutzky. Try the below and see if works or not
create procedure test
as
begin
return 1009;
end
declare #var int;
exec #var = test;
select #var;

Getting an error in sql

I am getting this error:
Procedure or function 'NewEmployee' expects parameter '#LastName', which was not supplied
This is what I have:
CREATE PROCEDURE NewEmployee1 (
#LastName nvarchar(75)
,#FirstName nvarchar(50)
,#HireDate datetime
,#Birthdate datetime
,#Title nvarchar(30))
WITH EXECUTE AS CALLER
AS
BEGIN
Set NOCOUNT ON;
Begin Try
Begin Transaction;
INSERT INTO Employees (LastName,FirstName,HireDate,BirthDate,Title)
VALUES (#LastName, #FirstName, #HireDate,#Birthdate,#Title)
COMMIT TRANSACTION;
End Try
Begin Catch
--Rollback any active or uncommitable transactions before
--inserting information in the errorLog
If ##Trancount > 0
Begin
Rollback Transaction;
End
Execute NewEmployee1 ;
End Catch;
End;
Exec NewEmployee
#LastName = 'Halpert',
#FirstName = 'Jim',
#HireDate = '11/14/2011',
#BirthDate = '04/02/1971',
#Title = 'Sales';
Should I have it like #lastName nvarchar(75) = Null?
You have the line Execute NewEmployee1 ; which attempts to execute the stored procedure with no parameters.
If you want default values assigned to parameters, you need to do as you suggested...
CREATE PROCEDURE NewEmployee1 (
#LastName nvarchar(75) = NULL
,#FirstName nvarchar(50) = NULL
,#HireDate datetime = NULL
,#Birthdate datetime = NULL
,#Title nvarchar(30) = NULL
)
Or replacing the NULLs with any appropriate default value.
You define the procedure as NewEmployee1, but then you call NewEmployee.
EDIT:
I think that calling Execute NewEmployee1 ; in the CATCH statement could potentially cause an infinite loop if there were some problem calling the stored procedure with the default values... Are you sure you want to call the SP again in the CATCH?
I see
CREATE PROCEDURE **NewEmployee1**
while you later on call it using
Exec NewEmployee
withiout the 1 at the end of the name.
Probably you have another procedure NewEmployee, which does not have a param #LastName.

Get scalar value from SELECT statement in stored proc, from within a stored proc

I know the preferred method for returning scalar values from stored procs is either using RETURN or an OUTPUT parameter. But lets say that I have a stored proc that returns the value using a select statement:
CREATE PROC spReturnNumber AS
SELECT 1
Is it possible to get this value from within another stored proc?
CREATE PROC spCheckNumber AS
EXEC spReturnNumber -- <-- get the return value here?
Clarification: I need a solution that doesn't require using an OUTPUT parameter, or using RETURN to return the value.
Thanks in advance.
You could use insert-exec to store the result of a stored procedure in a table:
declare #t table (col1 int)
insert #t exec spReturnNumber
return (select col1 from #t)
The definition of the table has to match the result set of the stored procedure.
Use an OUTPUT parameter instead of (or in addition to, if this procedure is used by other applications) the SELECT.
ALTER PROCEDURE dbo.spReturnNumber
#Number INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
SET #Number = 1;
SELECT #Number;
END
GO
CREATE PROCEDURE dbo.spCheckNumber
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Number INT;
EXEC dbo.spReturnNumber #Number = #Number;
SELECT #Number;
END
GO
If you can't change the original procedure, but you know its output will remain static, you could use a #temp table.
CREATE PROCEDURE dbo.spCheckNumber
AS
BEGIN
SET NOCOUNT ON;
CREATE TABLE #n(i INT);
INSERT #n(i) EXEC dbo.spReturnNumber;
DECLARE #Number INT;
SELECT #Number = i FROM #n;
END
GO
You can't get the SELECT value from "parent" procedure but you can get the return value like this:
CREATE PROC A AS
BEGIN
DECLARE #ret int
EXEC #ret = spReturnNumber
RETURN #ret
END
If you are unable to change the proc being called .. place the result set in a temp table [or table variable]:
CREATE TABLE #results (val INT)
DECLARE #someval int
INSERT #results
EXEC dbo.spCheckNumber
SELECT #someval =val from #results