I'm writing a stored procedure and I want to return 0 records when something fails. I can't seem to figure out how to just return 0 rows? I've used SELECT NULL
but this returns 1 row with a NULL
in row 1 col 1. I have also tried not specifying any SELECT
statements in my error code path but when testing the value of @@ROWCOUNT
after the call to the SP, it returned 1. I think this may be because the @@ROWCOUNT
was never reset from the SELECT
statement earlier in the SP (in the EXISTS()
). Any advice would be appreciated.
Also, I've got XACT_ABORT
set to ON, but I have also used a TRY/CATCH
block to ensure I return the correct error "return value" from the stored procedure. Is this okay? If there is an error, will the XACT_ABORT
override the TRY/CATCH
or will my error code path still lead to the correct return values being returned?
-- Setup
SET NOCOUNT ON; -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET XACT_ABORT ON; -- SET XACT_ABORT ON rollback transactions on errors
DECLARE @return int; SET @return = 1; -- Default to general error
-- Start transaction
BEGIN TRANSACTION
BEGIN TRY
IF NOT EXISTS(SELECT NULL FROM [MyTable] WHERE [Check] = 1)
BEGIN
-- Insert new record
INSERT INTO [MyTable] (Check, Date) VALUES (1, GETDATE());
SELECT SCOPE_IDENTITY() AS [MyValue]; -- Return 1 row
SET @return = 0; -- Success
END
ELSE
BEGIN
-- Fail
SELECT NULL AS [MyValue]; -- Want to return 0 rows not 1 row with NULL
SET @return = 2; -- Fail error
END
END TRY
BEGIN CATCH
-- Error
ROLLBACK TRANSACTION;
SELECT NULL AS [MyValue]; -- Want to return 0 rows not 1 row with NULL
SET @return = 1; -- General error
END CATCH
-- End transaction and return
COMMIT TRANSACTION
RETURN @return;
When SET XACT_ABORT is ON, if a Transact-SQL statement raises a run-time error, the entire transaction is terminated and rolled back. When SET XACT_ABORT is OFF, in some cases only the Transact-SQL statement that raised the error is rolled back and the transaction continues processing.
If you try to return NULL from a stored procedure using the RETURN keyword, you will get a warning, and 0 is returned instead. If a procedure hits an error that requires it to terminate immediately, it will return NULL because it never gets to either the RETURN keyword or the end of the batch!
You can use one or more RETURN statements in a stored procedure. The RETURN statement can be used anywhere after the declaration blocks within the SQL-procedure-body. To return multiple output values, parameters can be used instead. Parameter values must be set before the RETURN statement runs.
In SQL Server you can take advantage of TRY... CATCH statements to handle errors. When writing code that handles errors, you should have a TRY block and a CATCH block immediately after it. The TRY block starts with a BEGIN TRY statement and ends with an END TRY statement.
To return 0 rows, you can do:
SELECT TOP 0 NULL AS MyValue
Personally, I'd use an OUTPUT parameter for this sproc to return the ID back out instead of returning a resultset - that's just my preference though. Then just set that output parameter to e.g. -1 as default to indicate nothing done.
this is how I'd do it:
CREATE PROCEDURE YourProcedure
AS
( @NewMyValue int OUTPUT --<<<<<use output parameter and not a result set
)
BEGIN TRY
--<<<<put everything in the BEGIN TRY!!!
-- Setup
SET NOCOUNT ON; -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
SET XACT_ABORT ON; -- SET XACT_ABORT ON rollback transactions on errors
DECLARE @return int
--<<init multiple variables in a select, it is faster than multiple SETs
--set defaults
SELECT @return = 1 -- Default to general error
,@NewMyValue=NULL
-- Start transaction
BEGIN TRANSACTION --<<<put the transaction in the BEGIN TRY
--<<<lock rows for this transaction using UPDLOCK & HOLDLOCK hints
IF NOT EXISTS(SELECT NULL FROM [MyTable] WITH (UPDLOCK, HOLDLOCK) WHERE [Check] = 1)
BEGIN
-- Insert new record
INSERT INTO [MyTable] (Check, Date) VALUES (1, GETDATE());
SELECT @NewMyValue=SCOPE_IDENTITY() --<<<set output parameter, no result set
,@return = 0; -- Success
END
ELSE
BEGIN
-- Fail
--<<no need for a result set!!! output parameter was set to a default of NULL
SET @return = 2; -- Fail error
END
COMMIT TRANSACTION --<<<commit in the BEGIN TRY!!!
END TRY
BEGIN CATCH
-- Error
IF XACT_STATE()!=0 --<<<only rollback if there is a bad transaction
BEGIN
ROLLBACK TRANSACTION
END
--<<any insert(s) into log tables, etc
--<<no need for a result set!!! output parameter was set to a default of NULL
SET @return = 1; -- General error
END CATCH
-- End transaction and return
RETURN @return;
GO
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With