Requirement for explicit transaction statements when using SET XACT_ABORT ON? - sql

If I use SET XACT_ABORT ON in CREATE PROCEDURE statement, do I have to wrap all my statements under explicit transaction statements: BEGIN TRANSACTION and COMMIT?
Or does SET XACT_ABORT ON terminate procedure execution regardless of these in the case of execution error?

XACT_ABORT is typically for when someone has coded a transaction in a stored procedure, when maybe they should have left this responsibility to the calling module.
When something goes wrong, a transaction can remain open with the caller being oblivious to it. Setting XACT_ABORT to ON means that the transaction is not left open in the event of a failure.
When using transaction, you should really always look to handle every possible error within the SQL and deal with the transaction accordingly. Better still, strip the transactions from the SQL altogether, and rely on the calling module.

Related

Uncommitted transaction asking every time in SQL Server 2012

I am facing issues like whenever I open SQL windows and run any SQL transaction (insert, update or delete or any modification in procedure), it asks about uncommitted transaction.
How to fix this permanently?
Sounds like you probably have SET IMPLICIT_TRANSACTIONS on.
This will open a new transaction implicitly when it encounters statements such as insert, update or delete and no transaction is open and will require an explicit commit or rollback.
Implicit transactions may unexpectedly be ON due to ANSI defaults. For details see SET ANSI_DEFAULTS (Transact-SQL).
IMPLICIT_TRANSACTIONS ON is not popular. In most cases where IMPLICIT_TRANSACTIONS is ON, it is because the choice of SET ANSI_DEFAULTS ON has been made.
You need to go into the connection properties and ensure you have not enabled implicit transactions either explicitly or implicitly.
When you use BEGIN TRANSACTION you also need to either COMMIT TRANSACTION if it has done all the work you want correctly or ROLLBACK TRANSACTION if there has been issues and you want to return to the state before the start of the transaction.
Read up on transactions here

Is a ROLLBACK TRANSACTION statement necessary

When opening an explicit transaction if a failure occurs will all statements between the BEGIN and COMMIT automatically be rolled back? Or do you have to issue a ROLLBACK statement.
In my previous experience everything between the BEGIN and COMMIT automatically rolled back. Therefore what constitutes when you need to issue a ROLLBACK statement to manually roll it back?
It depends upon your session settings and the type of error. If it is a statement-terminating error, then the transaction just continues with the next statement. If it's a batch-terminating error, then the transaction is aborted.
To avoid issues with statement-terminating errors, make sure you have previously executed:
SET XACT_ABORT ON;
and then all statement-terminating errors will also abort the transaction and roll back.
Some programming client libraries turn that on automatically for you, and that's why you may have previously seen the auto-rollback, but I usually add it as the first line of all my stored procedures, just to be sure.

Can i return SQL procedure before committing the transaction?

Can i use return statement in a sql transaction procedure?
Sql Procedure
ALTER PROCEDURE [dbo].[uspProcessStudentRecord]
AS
Begin Transaction
insert into dbo.Student(name,address) values('ABC','INDIA');
return;
Commit Transaction
Is it a good practice of writing return inside a Transaction?
Is it a good practice of writing return inside a Transaction?
No. In fact you will get this SQL Server error and the transaction will remain uncommitted:
Transaction count after EXECUTE indicates a mismatching number of
BEGIN and COMMIT statements. Previous count = 0, current count = 1.
When a transaction is started in a stored procedure, the best practice is to COMMIT or ROLLBACK prior to returning. Also, it's a good practice to specify SET XACT_ABORT ON in procs with explicit transactions to avoid inadvertently leaving a transaction open after a timeout.
rollback transaction will undo it.
returning it will do nothing if you didn't commit it first.
But i do not see any point of doing what you are doing now in your statement unless you are going to use a try catch or some other statement.
If you really do want to be able to commit even if the transaction is rolled back (and the only viable reason I can think of is for logging purposes) there are a couple of options open to you:
Use the Service Broker with event notifications link
Use a linked server pointing back to same DB instance without distributed transaction promotion - this will commit in a completely isolated transaction.
But please first reconsider if this is something you really need to do!

Are T-SQL rollbacks deterministic or garbage collected?

In our Miscrosoft Sql Server 2008 database, I found some stored procedures that do this:
BEGIN TRY
BEGIN TRANSACTION
query1
query2
query3
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
RAISERROR
END CATCH
I said to my coworker that this is functionally identical to this:
BEGIN TRANSACTION
query1
query2
query3
COMMIT TRANSACTION
If, say, query2 fails, you never hit the COMMIT line, so of course SqlServer rolls back, and because of the error, it throws it back to the client as well. Since the CATCH block does the same thing as the default, I argued that we don't need the TRY/CATCH block at all.
My co-worker agrees that the ROLLBACK will happen eventually, but it could be some time later, and could hold resources or lock records for some non-deterministic amount of time, and this could cause problems.
So my question is: if a stored procedure fails in a transaction, when does that transaction get rolled back?
The rollback won't be triggered with your solution in the expected way.
You have to add
set xact_abort on
to your query.
For further information see an old answer and the Microsoft documentation
SQL Server will happily leave the transaction open forever as long as the client connection remains open. An explicit rollback is a good practice in that it doesn't wait for the client connection to be physically closed or the pooled connection reused. A simple THROW (SQL 2012 and later) in the CATCH block will rollback the transaction and raise the error.
I recommend the SET XACT_ABORT ON option hash suggested to mitigate a another issue. If a client timeout occurs during query execution, no further code in the batch (including the ROLLBACK) will execute and the transaction will be left open. However, the transaction will still get rolled back with SET XACT_ABORT ON.

How does SQL Server treat statements inside stored procedures with respect to transactions?

Say I have a stored procedure consisting of several separate SELECT, INSERT, UPDATE and DELETE statements. There is no explicit BEGIN TRANS / COMMIT TRANS / ROLLBACK TRANS logic.
How will SQL Server handle this stored procedure transaction-wise? Will there be an implicit connection for each statement? Or will there be one transaction for the stored procedure?
Also, how could I have found this out on my own using T-SQL and / or SQL Server Management Studio?
Thanks!
There will only be one connection, it is what is used to run the procedure, no matter how many SQL commands within the stored procedure.
since you have no explicit BEGIN TRANSACTION in the stored procedure, each statement will run on its own with no ability to rollback any changes if there is any error.
However, if you before you call the stored procedure you issue a BEGIN TRANSACTION, then all statements are grouped within a transaction and can either be COMMITted or ROLLBACKed following stored procedure execution.
From within the stored procedure, you can determine if you are running within a transaction by checking the value of the system variable ##TRANCOUNT (Transact-SQL). A zero means there is no transaction, anything else shows how many nested level of transactions you are in. Depending on your sql server version you could use XACT_STATE (Transact-SQL) too.
If you do the following:
BEGIN TRANSACTION
EXEC my_stored_procedure_with_5_statements_inside #Parma1
COMMIT
everything within the procedure is covered by the transaction, all 6 statements (the EXEC is a statement covered by the transaction, 1+5=6). If you do this:
BEGIN TRANSACTION
EXEC my_stored_procedure_with_5_statements_inside #Parma1
EXEC my_stored_procedure_with_5_statements_inside #Parma1
COMMIT
everything within the two procedure calls are covered by the transaction, all 12 statements (the 2 EXECs are both statement covered by the transaction, 1+5+1+5=12).
You can find out on your own by creating a small stored procedure that does something simple, say insert a record into a test table. Then Begin Tran; run sp_test; rollback; Is the new record there? If so, then the SP ignores the outside transaction. If not, then the SP is just another statement executed inside the transaction (which I am pretty sure is the case).
You must understand that a transaction is a state of the session. The session can be in an explicit transaction state because there is at least one BEGIN TRANSACTION that have been executed in the session wherever the command "BEGIN TRANSACTION" has been throwed (before entering in a routine or inside the routine code). Otherwise, the state of the session is in an implicit transaction state. You can have multiple BEGIN TRANSACTION, but only the first one change the behavior of the session... The others only increase the ##TRANCOUNT global sesion variable.
Implicit transaction state means that all SQL orders (DDL, DML and DCL comands) wil have an invisble integrated transaction scope.