If I raise an error in an AFTER UPDATE trigger in Sql Server 2005, will that cause the update which caused the trigger to be fired to roll back, even if the statement was not executed within a transaction?
Thanks.
No, you have to rollback transaction by calling ROLLBACK TRAN:
CREATE TRIGGER trg_au_table
ON dbo.table
AFTER UPDATE
AS
BEGIN
ROLLBACK TRAN
END
GO
This example will prevent from updating any record.
This:
CREATE TRIGGER trg_au_table
ON dbo.table
AFTER UPDATE
AS
BEGIN
RAISERROR('This is a test', 16, 1)
END
GO
will only raise the error but the change will be made in the table.
Related
I'm involved in new project right now and I faced with below logic in Sybase ASE trigger:
CREATE TRIGGER TR_TEST2
ON TBL_TEMP2
FOR INSERT
AS
insert into TBL_TEMP select * from inserted
if ##error != 0
begin
print 'ERROR!!!'
rollback trigger
end
I've checked this trigger with different cases and I can't understand when if ##error != 0 will be treated.
If there are some errors in INSERT, the trigger just fails with error and rolled back. And trigger execution will be aborted on the statement which raised error
Can someone explain me for what purposes if ##error != 0 is used in triggers and when it can trigger?
I've used for testing Sybase Central v.6.0
And it does't show any PRINT results if error occurs
When I've used QTODBC tool for connecting to Sybase ASE server, it threw me exception and printed 'ERROR!!!' message
So, this is the feature of Sybase Central environment
Actually, trigger resumes working when any error occurred
i have a loop while in sql which do something as it
begin tran one
do some inserts in others tables
--start loop
begin tran two
--do something
begin try
--if something fail then a trigger does rollback and this return a error (and this goes to catch), then don't i need do the rollbak in catch? this could not be dissable because this is working on production
--something finished ok
commit tran two
end try
begin catch
rollback tran two
end catch
--finished loop
commit
----------
i got this error
Uncommittable transaction is detected at the end of the batch. The
transaction is rolled back.
begin tran one
begin tran two
rollback tran two
doing this code i get this:
Cannot roll back two. No transaction or savepoint of that name was found.
I only want the subquery to rollback the second loop and continue with others records.
Operator rollback rolls back all transaction, for roll back only second loop you you must use savepoints:
begin tran one
-- do some inserts in others tables
--start loop
save tran two -- begin tran two
--do something
begin try
update product set id = 1 --if something fail then a trigger does rollback and this return a error (and this goes to catch), then don't i need do the rollbak in catch? this could not be dissable because this is working on production
--something finished ok
commit tran two
end try
begin catch
rollback tran two
end catch
--finished loop
commit
trigger example:
create table product (id int)
GO
create trigger product_trigger on product for update
as
set xact_abort off
if (select count(*) from inserted i join product p on i.id=p.id)=0 begin
if (##trancount>0) begin
/* rollback */
raiserror('product does not exist', 16, 1)
end
end
In my case, was my code was calling, thru an EF DbContext method, a SQL Server stored procedure, which contained a non-nested transaction.
Since, as #NotMe has already pointed-out, that "there is no such as a nested transaction in SQL Server", I began wondering whether my process was really transaction-nestingless.
Suspecting, that my DbContext had some guilt, I started checking on DbContext options, until DbContext.Configuration.EnsureTransactionsForFunctionsAndCommands = True caught my attention.
So, as soon as I changed it value to True, everything worked successfully.
MyDbContext.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
What happened?
Well, in my opinion, EF's ObjectContext.ExecuteFunction method was managing its own outer transaction as a wrapper to my stored procedure's inner transaction, so, when my stored procedure's ROLLBACK TRAN was hit, there was no pending transaction when EF's COMMIT/ROLLBACK code was hit.
Oddly enough, while gathering some references on EnsureTransactionsForFunctionsAndCommands property, I found that this default behaviour is due to one of the worst (in my opinion) EF team's decision ever, since it collides diretly with every ROLLBACK TRAN inside a T-SQL script.
For further details on EF, check insightfull SO's QA at EF6 wraps every single stored procedure call in its own transaction. How to prevent this?
Basically, everyone should check ##trancount > 0 before issuing a ROLLBACK command, whether named or not, specially inside stored procedure.
CREATE PROCEDURE Proc1 AS
BEGIN
BEGIN TRAN
EXEC Proc2
IF(##trancount > 0)
COMMIT TRAN
END
CREATE PROCEDURE Proc2 AS
BEGIN
BEGIN TRAN
ROLLBACK TRAN
END
For better awareness about Microsoft SQL Server's nested transactions, I would suggest reading the following article
Be careful using ROLLBACK on nested transaction in SQL Server!
Hope it helps someone :-)
Is there a way we can rollback to previous state of the transaction using ROLLBACK without BEGIN TRANSACTION?
delete from table1;
ROLLBACK
Message:
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
Any input would be of great help.
Thanks !!!
To expand on gerrytans answer when you explicitly set IMPLICIT_TRANSACTIONS ON, you can use a ROLLBACK. See the MSDN doco related to this. Note that this isn't the default autocommit transaction mode.
This allows me to run a statement like;
SET IMPLICIT_TRANSACTIONS ON
INSERT INTO my_table (item_type, start_date_time)
VALUES ('TEST', CURRENT_TIMESTAMP)
ROLLBACK
-- Shouldn't return the 'TEST' value inserted above.
SELECT * FROM my_table ORDER BY start_date_time DESC
As SQL server error tells you -- no you can't. And many people would be curious why would you want that in the first place.
Keep in mind SQL server has an implicit transaction -- that is for DML you issue without explicit BEGIN TRAN, SQL server will start and finish a transaction for you behind the screen.
A common usage of ROLLBACK is for error handling. If somewhere in the middle of the transaction you realize you cannot proceed further due to bad user input or other reason -- then a reasonable action is to ROLLBACK to return to the starting point
The worst thing that can happen is leave your data state 'somewhere in the middle'.
You must have a BEGIN TRANSACTION before you can use the ROLLBACK command. You can't go back to the previous state.
I have a replicated subscriber table on SQL Server 2008. I have put a trigger on it that may or may not fail. The table is read only.
My question is :
If I use the following
SAVE TRANSACTION savepoint1
BEGIN TRY
...
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION savepoint1
END CATCH
to rollback the transaction if there is some error in my trigger (in the ... part), will SQL Server attempt to update or rollback the read only subscriber table still causing an error?
Thanks.
Are you putting the trigger on the publisher where it will work? And you don't want it to work on the subscriber but you don't know how to disable it?
If that's true, you might try the NOT FOR REPLICATION tag on the trigger:
http://msdn.microsoft.com/en-us/library/ms176072.aspx
i need to update a database where some of the table have changed (columns have been added). I want to perform this action in a proper transaction. If the code executes without any problem then i will commit the changes otherwise i will rollback the database back to its original state.
I want to do something like this:
BEGIN TRANSACTION
...Execute some sql statements here
COMMIT TRANSACTION (When every thing goes well)
ROLLBACK TRANSACTION (When something goes wrong)
Please tell me what is the best way to do this i know there is a ##TranCount variable but dont know its exact purpose.
Thanks.
Begin Transaction
Alter Table dbo.MyTable
Add Col1 varchar(50)
If ##Error = 0
Begin
Commit Transaction
End
Else
Begin
Rollback Transaction
End
##Error gets reset after each SQL Statement so you must check it immediately after each statement has been executed to check for any errors.