SET XACT_ABORT ON not Worked in Create Procedure - sql

I use SQL Server 2008 SP3 (10.0.5500) And I have some Problems with Rollback Transactions, at first I need to know something. This is My create Procedure script:
USE [MYDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET XACT_ABORT ON
GO
If Exists(Select * From Sys.Objects Where [object_id]=Object_Id(N'[Members].[MyProc]') And ObjectProperty([object_id], N'IsProcedure') = 1)
Begin
Drop Procedure [Members].[MyProc]
Print 'Procedure [Members].[MyProc] Dropped!'
End
GO
CREATE PROCEDURE [Members].[MyProc](
....
)
AS
BEGIN
BEGIN TRANSACTION [MyProcCHK]
....
COMMIT TRANSACTION [MyProcCHK]
END
GO
And After run this script, I check Procedure from: MyDB ->Programmability->StoredProcedures And Click to Modify [Members].[MyProc] Then this is the script shown:
USE [MYDB]
GO
/****** Object: StoredProcedure ... ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [Members].[MyProc](
....
)
AS
BEGIN
BEGIN TRANSACTION [MyProcCHK]
....
COMMIT TRANSACTION [MyProcCHK]
END
GO
So Where is SET XACT_ABORT ON? And why that not displayed here? As I have some problems with rollback transactions in stored procedures I think the SET XACT_ABORT ON never saved. Am I right? and if yes, what is the solution? I can't use SET XACT_ABORT ON in stored procedures? or where is my fault?

You need to mention set xact_abort on inside the Create procedure statement
CREATE PROCEDURE [Members].[MyProc](
........
)
AS
SET XACT_ABORT ON
BEGIN
BEGIN TRANSACTION [MyProcCHK]
....
COMMIT TRANSACTION [MyProcCHK]
END
GO

Related

Create SQL Server procedure in a transaction

I need to create two procedures in a SQL Server transaction. If failure, I need to rollback the create(s) and any other executed queries in this transaction. I know the create statement must be the first statement in query batch, but I need to know how handle the transaction with multiple batches.
BEGIN TRANSACTION
CREATE PROCEDURE [dbo].[SP_SP-1]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SQL statements
END
GO
CREATE PROCEDURE [dbo].[SP_SP-2]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 statements
END
GO
UPDATE Table
SET Value = '1.0.0.5'
COMMIT TRANSACTION / ROLLBACK TRANSACTION
Below is one method to execute multiple batches in a transaction. This uses a temp table to indicate if any batch erred and perform a final COMMIT or ROLLLBACK accordingly.
Another method is to encapsulate statements that must be in single-statement batch (CREATE PROCEDURE, CREATE VIEW, etc.) but that can get rather ugly when quotes within the literal text must be escaped.
CREATE TABLE #errors (error varchar(5));
GO
BEGIN TRANSACTION
GO
CREATE PROCEDURE [dbo].[USP_SP-1]
#id bigint
AS
BEGIN
SET NOCOUNT ON;
-- SP Statments
END;
GO
IF ##ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
CREATE PROCEDURE [dbo].[USP_SP-2]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 Statments
END;
GO
IF ##ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
UPDATE Table SET Value='1.0.0.5'
GO
IF ##ERROR <> 0 INSERT INTO #errors VALUES('error');
GO
IF EXISTS(SELECT 1 FROM #errors)
BEGIN
IF ##TRANCOUNT > 0 ROLLBACK;
END
ELSE
BEGIN
IF ##TRANCOUNT > 0 COMMIT;
END;
GO
IF OBJECT_ID(N'tempdb..#errors', 'U') IS NOT NULL
DROP TABLE #errors;
GO
I suggest you to study more about this subject in Handling Transactions in Nested SQL Server Stored Procedures.
From the beginning, your syntax is wrong. You cannot begin a transaction and then create a procedure, you need to do just the opposite:
CREATE PROCEDURE [dbo].[SP_SP-1]
#id bigint
AS
BEGIN
BEGIN TRY
BEGIN TRANSACTION
SET NOCOUNT ON;
-- SP-2 Statments
Update Table set Value='1.0.0.5'
END TRY
BEGIN CATCH
--handle error and perform rollback
ROLLBACK
SELECT ERROR_NUMBER() AS ErrorNumber
SELECT ERROR_MESSAGE() AS ErrorMessage
END CATCH
END
It is best practice to use TRY and CATCH when attempting to perform update inside transaction scope.
Please read more and investigate using the link I provided to get a bigger picture.
To use Transaction, you need to know what is the meaning of transaction. It's meaning of 'Unit of work either in commit state or rollback state'.
So when you use transaction, you must know that where you declare and where you close. So you must start and end transaction in the parent procedure only than it will work as a unit of work i.e. whatever no of query execute of DML statement, it uses the same transaction.
I do not understand why your update statement outside of procedure and transaction portion too.
It should be (See my comments, you can use TRY Catch same as c sharp) :
Create PROCEDURE [dbo].[SP_SP-1]
#id bigint
AS
BEGIN
Begin Transaction
SET NOCOUNT ON;
-- SP Statments
Exec SP_SP-2 #id --here you can pass the parameter to another procedure, but do not use transaction in another procedure, other wise it will create another transaction
If ##Error > 0 than
Rollback
Else
Commit
End
END
GO
--Do not use transaction in another procedure, otherwise, it will create another transaction which has own rollback and commit and do not participate in the parent transaction
Create PROCEDURE [dbo].[SP_SP-2]
#id BIGINT
AS
BEGIN
SET NOCOUNT ON;
-- SP-2 Statments
END
GO
i find this solution to execute the procedure as string execution , it`s a workaround to execute what i want
Begin Try
Begin Transaction
EXEC ('
Create PROCEDURE [dbo].[SP_1]
#id bigint
AS
BEGIN
SET NOCOUNT ON;
SP-1
END
GO
Create PROCEDURE [dbo].[SP_Inc_Discovery_RunDoc]
#id bigint
AS
BEGIN
SET NOCOUNT ON;
Sp-2
END')
Update Table set Value='1.0.0.5'
Commit
End Try
Begin Catch
Rollback
Declare #Msg nvarchar(max)
Select #Msg=Error_Message();
RaisError('Error Occured: %s', 20, 101,#Msg) With Log;
End Catch

disable automatic auto code formatter sql server

I create a stored procedure like this in ssms:
USE [UnitTest]
GO
/****** Object: StoredProcedure [dbo].[ProcedureName] Script Date: 2017-09-18 15:30:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ProcedureName]
#p1 INT=0, #p2 INT=0
AS
BEGIN
SET NOCOUNT ON;
SELECT #p1,
#p2;
END
GO
but when I save the stored procedure and reopen it, automatically ssms changes the format like this:
USE [UnitTest]
GO
/****** Object: StoredProcedure [dbo].[ProcedureName] Script Date: 2017-09-18 15:29:28 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[ProcedureName]
#p1 INT=0,
#p2 INT=0
AS
BEGIN
SET NOCOUNT ON;
SELECT #p1, #p2;
END
GO
how can I disable this feature?
in Sql Management Studio to disable SQL autoformat when typing brackets:
Go To menu Tools --> Options --> Text Editor --> Transact SQL --> General and disable the checkbox AutoList Members
Im this menu you can find similar action sthat may solve your specific question

Unable to Use Transactions with Go statement in SQL Server 2008

BEGIN TRY
BEGIN TRANSACTION
SET ANSI_NULLS ON
Go
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION dbo.RerurnStaticValue
(
#value nvarchar(10)
)
RETURNS varchar(max)
AS
BEGIN
DECLARE
#ReturnValue nvarchar(10)
SET #ReturnValue = #value
RETURN #ReturnValue
END
COMMIT TRAN -- Transaction Success!
END TRY
BEGIN CATCH
IF ##TRANCOUNT > 0
ROLLBACK TRAN --RollBack in case of Error
select ERROR_MESSAGE()
END CATCH
I am preparing a very long script and try to implement the transaction in the script so in case if there will be any error in my script it will not effect my database. But I am getting the error Create function must be the only statement in the batch when implementing transactions.
Please help.
I think the documentation on functions is pretty clear:
User-defined functions cannot be used to perform actions that modify
the database state.
COMMIT/ROLLBACK definitely fall into this category.
Use a stored procedure instead.

SQLDependency throwing thousands of invalid notifications with stored proc

I've built a vb.net service to update Exchange appointments as appointment changes are made in our accounting suite. Everything works fine if I run the SQL query straight from VB.net but if I reference a stored proc with the exact same code I receive thousands of "invalid" notifications. I was wondering if anyone could tell me why?
I'm using VS2012, SQL Server 2008, and .NET 4.0
I pass each "option" into the query string and execute it before starting the dependency with this query:
select Dispatch_Id, Schedule_Time, Dispatch_Time, Arrival_Time, Departure_Time from dbo.Ticket_Dispatch
The stored proc is:
USE [database]
GO
/****** Object: StoredProcedure [dbo].[watch] Script Date: 1/22/2014 5:28:28 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:
-- Create date:
-- Description:
-- =============================================
ALTER PROCEDURE [dbo].[watch]
-- Add the parameters for the stored procedure here
AS
BEGIN
SET ANSI_NULLS ON;
SET ANSI_PADDING ON;
SET ANSI_WARNINGS ON;
SET CONCAT_NULL_YIELDS_NULL ON;
SET QUOTED_IDENTIFIER ON;
SET NUMERIC_ROUNDABORT ON;
SET ARITHABORT ON;
select Dispatch_Id, Schedule_Time, Dispatch_Time, Arrival_Time, Departure_Time from dbo.Ticket_Dispatch
END
Before any of this I test for permissions. The user has ownership over the table and the proc so there shouldn't be any problems there.

Mix Create Stored Procedure and Insert Statements in Sql Server

I created a number of scripts to be run separately but was asked to combine them all so the DBA only has to do it once. The problem is that I cannot seem to combine them to run together. Only the first item in the query gets run. How do I format these to run together in one big script?
USE [DEV]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[Projects]
#ProjectID int,
#ClientID int
AS
BEGIN
.....Cool procedure here
END
GRANT EXECUTE ON [dbo].[Projects] TO Admin, Employee
INSERT INTO random_table(stuff)
VALUES (stuff)
Add a GO between statements
USE [DEV]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[Projects]
#ProjectID int,
#ClientID int
AS
BEGIN
.....Cool procedure here
END
GO -- Add GO here
GRANT EXECUTE ON [dbo].[Projects] TO Admin, Employee
GO -- Add GO here
INSERT INTO random_table(stuff)
VALUES (stuff)
USE [DEV]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[Projects]
#ProjectID int,
#ClientID int
AS
BEGIN
.....Cool procedure here
END
GRANT EXECUTE ON [dbo].[Projects] TO Admin, Employee
GO -- added this "go" statement
INSERT INTO random_table(stuff)
VALUES (stuff)
Insert GO after each statement.
USE [DEV]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[Projects]
#ProjectID int,
#ClientID int
AS
BEGIN
.....Cool procedure here
END
GO //add Go after every statement
GRANT EXECUTE ON [dbo].[Projects] TO Admin, Employee
GO
INSERT INTO random_table(stuff)
VALUES (stuff)
Although, I would recommend you to generate script of Database schema (including Stored procedures, functions, table creation, insertion, updation and deletion) from your SQL server database and save it with .SQL file and you don't have to place these GOs manually. Take a look at this fine example