Are all statements in a stored procedure ONE transaction - sql-server

If a stored procedure contains multiple statements e.g. first an insert, then an update and finally a deletes and the stored procedure gets killed in the middle of the delete, does the insert and update also have to be rolled back? Or does it only roll back the delete i.e. the implicit transaction?

As explained in Transactions, each statement will be executed as an implicit transaction. If a statement fails then the effect of prior statements will remain committed.
Note that the entire stored procedure may be executed within an explicit transaction created by the calling code.

insert and update have to be commited but delete Statement was rolled back

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 an error.
However, if 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.
Reference: KM.
How does SQL Server treat statements inside stored procedures with respect to transactions?

Related

Force rollback to entire script (stored procedure included)

I have a complex script that contains many stored procedures and I need to do a rollback in all cases.
BEGIN TRANSACTION;
INSERT INTO Table1 VALUES(1);
INSERT INTO Table2 VALUES(2);
EXEC storedprocedure1
EXEC storedprocedure2
....
ROLLBACK;
I have not checked all stored procedures inside (if there is or not other transaction).
I ask if there is a way to rollback the entire script (stored procedures included) independently by presence of other transaction inside the stored procedures.
Thanks!
(Assuming SQL Server)
There is no need to check inside those stored procedures.
The ROLLBACK will rollback all the way to the outer-most transaction, including rolling-back all transactions within storedprocedure1 and storedprocedure2, even if those nested transactions are committed within those procedures.
Selecting ##TRANCOUNT will show you that any ROLLBACK sets the transaction count of the session back to 0.
So if you rollback the outer transaction, anyone who may be expecting those nested transactions to commit is going to be disappointed.

Stored procedure with multiple updates, insert and deletes. What happens if last DML command fails?

So, if I have multiple DML commands inside a stored procedure in SQL Server, if the last one fails, will all the other ones rollback? Considering I am not inside a transaction scope!
You need your stored procedure to use TRY CATCH and a TRANSACTION .
BEGIN TRAN
BEGIN TRY
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- if error, roll back any changes done by any of the SQL statements
ROLLBACK TRANSACTION
END CATCH
Refer to this
http://techfunda.com/howto/192/transaction-in-stored-procedure

Inserted records getting committed in DB without committing it manually

I have created a database transaction and I am inserting records in Table1 of H2 DB. But no commits done yet.
In between this process, after executing half of the records, I execute one create statement(created Table2).
Table2 is created and along with it, previous INSERT statements are also getting committed in DB.
After this, I'm inserting more records in Table1, if there is a failure in insertion, I still see records in Table1 which were inserted before create statement for Table2.
Due to this, I see some records in DB even after transaction failure. I was expecting ZERO records in DB.
Why is this happening?
Because create table is a DDL statement and no DML statement. And DDL statement usually commit any open transaction.
If you want to avoid this you should create all objects you need during the import before you import the first record.
EDIT 2019-03-22
Although this topic is a bit old I like to mention one thing which could help. You could create a procedure which uses PRAGMA AUTONOMOUS_TRANSACTION which executes an sql statement via execute immediate
PROCEDURE exec_sql_autonomous(p_sql VARCHAR2)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
EXECUTE IMMEDIATE p_sql;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
RAISE;
END;
This way you may be able to create a table while the data inserting transaction is in progress without committing it due to the table creation.

Statement execution in stored procedure in SQL Server

I have a stored procedure (simplified version) as below. In general it will push the pending items to email queue and update the status of those items to pushed. This stored procedure has been called in a 60 seconds interval.
ALTER PROCEDURE [dbo].[CreateEmailQueue]
AS
BEGIN
insert into EmailQueue
select *
from actionstatus
where actionstatus='Pending'
update actionstatus
set actionstatus = 'Pushed'
where actionstatus = 'Pending'
END
It works fine but I found one exception record. The exception's action status has been changed to "Pushed" but the record did not appear in the EmailQueue. I suspected that the action status record has been generated after the insert but before the update. But I am not 100% sure as I assume that SQL Server always execute a stored procedure in an isolation block so the data change won't affect the data set inside the execution. Could someone help explain the actual process inside the stored procedure, review this stored procedure and advise if it is OK, or it should be put in a transaction block? and, any performance or locking issue for doing this in transaction? Thanks for your input.
You must use transactins inside stored procedure. SQL Server don't generate transactions for stored procedures calls automatically. You can simply check it by execute code something like taht:
insert ...
--this will falls
select 1/0
Insertion will be done and than you'll have division by zero error

How can I ensure that nested transactions are committed independently of each other?

If I have a stored procedure that executes another stored procedure several times with different arguments, is it possible to have each of these calls commit independently of the others?
In other words, if the first two executions of the nested procedure succeed, but the third one fails, is it possible to preserve the results of the first two executions (and not roll them back)?
I have a stored procedure defined something like this in SQL Server 2000:
CREATE PROCEDURE toplevel_proc ..
AS
BEGIN
...
while #row_count <= #max_rows
begin
select #parameter ... where rownum = #row_count
exec nested_proc #parameter
select #row_count = #row_count + 1
end
END
First off, there is no such thing as a nested transaction in SQL Server
However, you can use SAVEPOINTs as per this example (too long to reproduce here sorry) from fellow SO user Remus Rusanu
Edit: AlexKuznetsov mentioned (he deleted his answer though) that this won't work if a transaction is doomed. This can happen with SET XACT_ABORT ON or some trigger errors.
From BOL:
ROLLBACK TRANSACTION without a
savepoint_name or transaction_name
rolls back to the beginning of the
transaction. When nesting
transactions, this same statement
rolls back all inner transactions to
the outermost BEGIN TRANSACTION
statement.
I also found the following from another thread here:
Be aware that SQL Server transactions
aren't really nested in the way you
might think. Once an explict
transaction is started, a subsequent
BEGIN TRAN increments ##TRANCOUNT
while a COMMIT decrements the value.
The entire outmost transaction is
committed when a COMMIT results in a
zero ##TRANCOUNT. But a ROLLBACK
without a savepoint rolls back all
work including the outermost
transaction.
If you need nested transaction
behavior, you'll need to use SAVE
TRANSACTION instead of BEGIN TRAN and
use ROLLBACK TRAN [savepoint_name]
instead of ROLLBACK TRAN.
So it would appear possible.

Resources