Why isn't my insert procedure returning the ID of the newly inserted row? AND, when calling this procedure, why do I have to supply a value for #EventId? That column is a PK with IDENTITY.
IF OBJECT_ID ( 'vjsql.EventsINSERT', 'P') IS NOT NULL
DROP PROCEDURE EventsINSERT
GO
CREATE PROCEDURE EventsINSERT
#EventId int OUTPUT,
#EventDate datetime,
#Title varchar(100),
#IsActive bit
AS
BEGIN
INSERT INTO EventCalendar ( EventDate, Title, IsActive)
VALUES ( #EventDate, #Title, #IsActive)
SELECT #EventId = SCOPE_IDENTITY()
END
How are you making a call to the stored procedure?
This SP is returning the value of EventID by means of using OUTPUT parameters.
i.e. In programming terms, this is a procedure (not a function) that accepts an OUTPUT parameter which will be set with the value during the execution of the stored procedure.
For this, you will have to pass the variable for #EventID. The value of which will be set within the procedure and you will be able to read the value of it, once the procedure has finished.
See the example code below.
DECLARE #NewEventID INT
EXEC EventsINSERT
#EventId = #NewEventID OUTPUT,
#EventDate = '08/04/09',
#Title = 'Hello World',
#IsActive = 0
SELECT #NewEventID
Try adding some statement terminators:
BEGIN
INSERT INTO EventCalendar ( EventDate, Title, IsActive)
VALUES ( #EventDate, #Title, #IsActive);
SELECT #EventId = SCOPE_IDENTITY();
END
AND, when calling this procedure, why do I have to supply a value for #EventId? That column is a PK with IDENTITY.
You don't, but you do need to supply a variable of type int (or compatible with int) for the output value to be put into.
You don't need to specify a value for the OUTPUT parameter, you need to specify which local variable the output gets put into:
By default, SQL Management Studio names the parameter and the variable the same, which can be confusing. Here's an example of your SP being called:
DECLARE #InsertedEventId int
EXEC [dbo].[EventsINSERT]
#EventId = #InsertedEventId OUTPUT,
#EventDate = N'2009-08-05',
#Title = N'Some event',
#IsActive = 1
-- Display ID as result set
SELECT #InsertedEventId
Just to clarify: your stored procedure is fine. I used it as-is.
Why isn't my insert procedure
returning the ID of the newly inserted
row?
Your code should work. Try in the console instead of
SELECT #EventId = SCOPE_IDENTITY()
doing
SELECT SCOPE_IDENTITY()
and view what happens. Is possible that you are calling it the wrong way. You should store the value of the OUTPUT variable in a variable in the scope where you call this SP.
when calling this procedure, why do I
have to supply a value for #EventId?
Because you have to supply a value for every parameter you have. It doesn't matter if is a real value, it will be discarded, but you must call the stored procedure with a variable in this parameter to catch the returned value.
I'm pretty rusty with tsql, but don't you need to explicitly select ##identity to get that row id? That's where i'd go digging as I think scope_identity() may not return a value in the context of a user function/procedure.
Related
I am writing a T-SQL stored procedure. I want to "set" a variable so that if
a parameter, it gets passed into the where clause (naturally).
But if nothing is specified for that parameter, I don't want this passed to
the where clause.
The reason is the default list is too long for me to specify.
How do I do this?
CREATE PROCEDURE Example
(#CompanyCode AS NVARCHAR(100) = NULL)
AS
SET NOCOUNT ON;
SELECT
.....
FROM
TableX
WHERE
(#CompanyCode IS NOT NULL AND Company = #CompandyCode)
OR
-- Does this work?
(#CompanyCode IS NULL)
You can just write:
Company = #CompandyCode OR #CompanyCode IS NULL
Yes that should work.
WHERE #companyCode IS NULL OR (#companyCode IS NOT NULL AND Company = #companyCode)
When exactly do we use stored procedures with output parameters and when do we use stored procedures without parameters?
I base my question on an example:
Stored procedure with output parameter
CREATE PROCEDURE uspGetContactsCountByCity
#City nvarchar(60),
#ContactsCount int OUT
AS
BEGIN
SELECT #ContactsCount = COUNT(ContactID)
FROM Contacts
WHERE City = #City
END
Stored procedure executing
DECLARE #ContactsTotal INT
EXEC uspGetContactsCountByCity #ContactsCount = #ContactsTotal OUT, #city = 'Berlin'
SELECT #ContactsTotal
Results: 2
Stored procedure without output parameter
CREATE PROCEDURE uspGetContactsCountByCity2
#City nvarchar(60)
AS
BEGIN
SELECT COUNT(ContactID)
FROM Contacts
WHERE City = #City
END
Stored procedure executing:
EXEC uspGetContactsCountByCity2 #city = 'Berlin'
Results: 2
Both procedures return the same result, in same form, so what's the difference?
Basically, the result you're seeing is actually the result of your SELECT at the end of the procedure, which is doing the same thing.
Please take a look at this documentation:
If you specify the OUTPUT keyword for a parameter in the procedure definition, the stored procedure can return the current value of the parameter to the calling program when the stored procedure exits. To save the value of the parameter in a variable that can be used in the calling program, the calling program must use the OUTPUT keyword when executing the stored procedure.
So basically if you would like your stored procedure to just return just a value instead of a data set, you could use the output parameter. For example, let's take the procedures you have given as an example. They both do the same thing, this is why you got the same result. But what about changing a little bit in the first procedure that has the output parameter.
Here's an example:
create table OutputParameter (
ParaName varchar(100)
)
insert into OutputParameter values ('one'), ('two'),('three'),('one')
CREATE PROCEDURE AllDataAndCountWhereOne
#name nvarchar(60),
#count int OUT
as
Begin
SELECT #count = COUNT(*) from OutputParameter
Where ParaName = #name
select Distinct(ParaName) from OutputParameter
End
Declare #TotalCount int
Exec AllDataAndCountWhereOne #count = #TotalCount OUT, #name = 'One'
Select #TotalCount
With this example, you are getting all the distinct stored data in the table, plus getting the count of a given name.
ParaName
--------------------
one
three
two
(3 row(s) affected)
-----------
2
(1 row(s) affected)
This is one way of using the output parameter. You got both the distinct data and the count you wanted without doing extra query after getting the initial data set.
At the end, to answer your question:
Both procedures gives us the same result, in same form, so what's the difference?
You didn't make a difference in your own results, this is why you didn't really notice the difference.
Other Examples:
You could use the OUT parameter in other kinds of procedures. Let's assume that your stored procedure doesn't return anything, it's more like a command to the DB, but you still want a kind of message back, or more specifically a value. Take these two examples:
CREATE PROCEDURE InsertDbAndGetLastInsertedId
--This procedure will insert your name in the database, and return as output parameter the last inserted ID.
#name nvarchar(60),
#LastId int OUT
as
Begin
insert into OutputParameterWithId values (#name);
SELECT #LastId = SCOPE_IDENTITY()
End
or:
CREATE PROCEDURE InsertIntoDbUnlessSomeLogicFails
--This procedure will only insert into the db if name does exist, but there's no more than 5 of it
#name nvarchar(60),
#ErrorMessage varchar(100) OUT
as
Begin
set #ErrorMessage = ''
if ((select count(*) from OutputParameterWithId) = 0)
begin
set #ErrorMessage = 'Name Does Not Exist'
return
end
if ((select count(*) from OutputParameterWithId) = 5)
begin
set #ErrorMessage = 'Already have five'
return
end
insert into OutputParameterWithId values (#name);
End
These are just dummy examples, but just to make the idea more clear.
An example, based on yours would be if you introduced paging to the query.
So the result set is constrained to 10 items, and you use a total count out parameter to drive paging on a grid on screen.
Answer from ozz regarding paging does not make sense because there is no input param that implements a contraint on the number of records returned.
However, to answer the question... the results returned by these stored procedures are not the same. The first returns the record count of contacts in given city in the out param ContactsCount. While the count may also be recieved in the second implement through examining the reader.Rows.Count, the actual records are also made a available. In the first, no records are returned - only the count.
I have a procedure , which return a single row of data.
CREATE PROCEDURE GetABCD
AS
declare #_Wsd varchar = 'England'
declare #_App varchar = '500'
declare #_Ver varchar = '1.0'
BEGIN
SET NOCOUNT ON;
select
#_Wsd as [WSDL_CODE]
,#_App as [APP_TYPE]
,#_Ver as [VERSION]
END
The procedure GetABCD is calling in another Procedure , and assign the three values to another variables in the calling procedure .
How can i achieve it ?
You will need to define the three values you want to return as OUTPUT values, and have the calling stored procedure use them from there on.
I.e. (pseudo code, i.e. untested)
CREATE PROCEDURE GetABCD
(
#_Wsd varchar = 'England' OUTPUT
, #_App varchar = '500' OUTPUT
, #_Ver varchar = '1.0' OUTPUT
)
select
#_Wsd as [WSDL_CODE]
,#_App as [APP_TYPE]
,#_Ver as [VERSION]
RETURN
More information here on MSDN.
You can then consume the variables from another query or procedure.
As stated, this is untested, so you might have to slightly adjust the code. If it throws any error, please let me know, and I will update the answer accordingly.
I'm stuck on assigned variable values in this stored procedure.
#EntityID int,
#Title1 varchar(10) OUTPUT,
#Title2 varchar(10) OUTPUT
AS
Declare #T1 varchar(10)
Declare #T2 varchar(10)
BEGIN
SELECT
dbo.Entity.EntityID, dbo.Types.TypeName AS Title1, Types_1.TypeName AS Title2
FROM
dbo.Entity
LEFT OUTER JOIN
dbo.Types AS Types_1 ON dbo.Entity.Title2 = Types_1.TypeID
AND dbo.Entity.Title2 = Types_1.TypeID
LEFT OUTER JOIN
dbo.Types ON dbo.Entity.Title1 = dbo.Types.TypeID
WHERE
(dbo.Entity.EntityID = #EntityID)
END
I'm trying to return the values of Title1 and Title2. The query works, and returns values, but I need to use them elsewhere.
You need to do two things:
First, set the values of those parameters somewhere in the PROC, using SELECT or SET. As #Andomar mentioned this can be done by changing your SELECT statement like this (in your existing code you are returning the values in a column with the same name but that won't actually set the parameters):
SELECT #Title1 = dbo.Types.TypeName, #Title2 = Types_1.TypeName
Then you need to capture those values in your calling program. I'm not sure whether you're calling this stored proc from another bit of SQL code or from code such as ADO.NET. If from SQL, you'll need to first declare the output parameters and then call the proc like this:
DECLARE #Title1 VARCHAR(10), #Title2 VARCHAR(10)
EXEC MyProc #Title1=#Title1 OUTPUT, #Title2=#Title2 OUTPUT
If you're calling from ADO.NET, you need to set the ParameterDirection as Output or InputOutput, call the proc with the parameter, and then read the value of the parameter afterwards.
SELECT #Title1 = dbo.Types.TypeName
, #Title2 = Types_1.TypeName
...
I'm new to SQL Server. Currently I'm working on an existing source code and I have some unclear point the stored procedure
For examples:
My_Stored_Procedure_1
CREATE PROC [dbo].[My_Stored_Procedure_1]
#ID INT,
#DATE DATETIME
AS
BEGIN
UPDATE query...
PRINT 'ID is ' + CAST(#ID AS VARCHAR(10))
END
My_Stored_Procedure_2
CREATE PROC [dbo].[My_Stored_Procedure_2]
#RESULT INT
AS
BEGIN
EXEC #RESULT = My_Stored_Procedure_1 // Unclear point
END
My question is that, I don't see any return value from the My_Stored_Procedure_1, so what will be returned to #RESULT variable? Maybe a default returned value of the executed stored procedure?
Thank you very much.
#Result will have default value that was passed while executing the Stored Procedure My_Stored_Procedure_2.
The statement EXEC #RESULT = My_Stored_Procedure_1 will execute with error and terminate the execution of My_Stored_Procedure_2 because you have not passing two input parameter to My_Stored_Procedure_1 sp while calling this.
The default value of a stored procedure is dependent on whether or not the statements in that procedure executed successfully. For example, if your UPDATE statement failed due to a constraint error, #RESULT would be set to -6. If it runs successfully with no error, it would normally be 0. See the following:
CREATE TABLE #testTable (Value INT, CHECK (Value > 5));
INSERT #testTable VALUES (6);
GO
CREATE PROCEDURE #testProc AS
UPDATE #testTable SET Value = 2;
GO
DECLARE #ret INT;
EXEC #ret = #testProc;
PRINT #ret; -- “-6”
DROP PROCEDURE #testProc;
DROP TABLE #testTable;
GO
Note that you never make an attempt to observe the value of #RESULT. Since #RESULT is not an OUTPUT parameter, the caller of "dbo"."My_Stored_Procedure_2" will not see the return value of "dbo"."My_Stored_Procedure_1". It looks like you are ignoring the return value. If you could alter your example to show how you are consuming the return value, that can help us understand your question and provide better advice.