I need to provide an auto update feature to my application.
I am having problem in applying the SQL updates. I have the updated SQL statement in my .sql file and what i want to achieve is that if one statment fails then entire script file must be rolled back
Ex.
create procedure [dbo].[test1]
@P1 varchar(200),
@C1 int
as
begin
Select 1
end
GO
Insert into test (name) values ('vv')
Go
alter procedure [dbo].[test2]
@P1 varchar(200),
@C1 int
as
begin
Select 1
end
GO
Now in the above example, if i get the error in third statement of “alter procedure [dbo].[test2]” then i want to rollback the first two changes also which is creating SP of “test1” and inserting data into “test” table
How should i approach this task? Any help will be much appreciated.
If you need any more info then let me know
Normally, you would want to add a
BEGIN TRANat the beginning, remove theGOstatements, and then handle theROLLBACK TRAN/COMMIT TRANwith aTRY..CATCHblock.When dealing with DML though there are often statements that have to be at the start of a batch, so you can’t wrap them in a
TRY..CATCHblock. In that case you need to put together a system that knows how to roll itself back.A simple system would be just to backup the database at the start and restore it if anything fails (assuming that you are the only one accessing the database the whole time). Another method would be to log each batch that runs successfully and to have corresponding rollback scripts which you can run to put everything back should a later batch fail. This obviously requires much more work (writing an undo script for every script PLUS fully testing the rollbacks) and can also be a problem if people are still accessing the database while the upgrade is happening.
EDIT:
Here’s an example of a simple
TRY..CATCHblock with transaction handling:However, the
TRY..CATCHblock cannot span batches (maybe that’s what I was thinking of when I said transactions couldn’t), so in your case it would probably be something more like:Unfortunately, because of the separate batches from the
GOstatements you can’t useGOTO, you can’t use theTRY..CATCH, and you can’t persist a variable across the batches. This is why I used the very kludgy trick of creating a table to indicate an error.A better way would be to simply have an error table and look for rows in it. Just keep in mind that your
ROLLBACKwill remove those rows at the end as well.