views:

662

answers:

7

I am writing an install script that installs all tables, stored procedures, views, full text indexs, users ect.

It all works fine if the user has all the correct permissions and the script runs from start to finish. However if the script dies somewhere midway through then it cannot just be run again.

To accomplish this I want to basically return the database to a "brand new" state where it has nothing.

I realize how to drop each table/sp/view.. on their own but I am looking for a more general way to reset the database.

I also need to be able to delete Fulltext Catalogs and users.

Thanks for any help.

Running SQL Server 2005

+7  A: 

Can you run the entire script within a transaction and then call a rollback if it fails?

A CREATE TABLE can be rolled back just as easily as an INSERT/UPDATE.

Robin Day
that is of course the way to go, nevermind my reply =)
David Hedlund
@d. I'm not sure why it's beter. It's for the users permissions or there is other reason?
Jonathan
I agree.. if a drop/create database is an option, you could easily go with that.
Robin Day
well, alright, there's discussion going on here and in my post, it's a bit tricky to keep up, perhaps we should edit and merge them? there's obviously advantages to both sides. what struck me (albeit after posting) as desirable with transactions is that it goes to the heart of the matter with the original request: if something *goes wrong* he wants to *reset*. transaction should be on the top of any dba's mind when a question is termed like that.
David Hedlund
+5  A: 

Sounds like a job for Drop Database

David Hedlund
I'd go this way for a couple of reasons. 1. You're assured that no "old" data is left in the database. 2. It keeps your dev/testing model honest by requiring that the database be built from scratch. If you add new tables, views, procedures, etc.. it should be part of the deploy/install/test cycle. Don't deploy a database, deploy the means to create it.
clintp
Agreed. You're *creating* the database, not maintaining an existing one; if you can't create it exactly the way you want it, you should be able to just drop it and retry.
Philip Kelley
+1  A: 

Brand new containing nothing? Drop the database and recreate it if you have permissions to do this.

David M
A: 

You can run the whole script in one transaction, so you will be able to rollback it at any point.

Second option - before installation always create a backup. If it fails, restore the database from backup

Bogdan_Ch
A: 

I'm not sure if this is what you're looking for, but for each object, you could test if exist before creating it. Then you could run again the script if it fails in the middle.

IF EXISTS(SELECT 1 FROM sys.objects WHERE object_id = OBJECT_ID(@Object) AND type = (@Type))

...

Jonathan
A: 

If you have your scripting process automated per object, you should be able to wrap the entire process in a transaction and provide error handling for each DDL statment. This also works well when applying schema updates. Please note, this is based upon upgrade scripts that Red-Gate SQL Compare generates.

Header:

SET NUMERIC_ROUNDABORT OFF
GO
SET ANSI_PADDING, ANSI_WARNINGS, CONCAT_NULL_YIELDS_NULL, ARITHABORT, QUOTED_IDENTIFIER, ANSI_NULLS ON
GO
IF EXISTS (SELECT * FROM tempdb..sysobjects WHERE id=OBJECT_ID('tempdb..#tmpErrors')) DROP TABLE #tmpErrors
GO
CREATE TABLE #tmpErrors (Error int)
GO
SET XACT_ABORT ON
GO
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
GO
BEGIN TRANSACTION
GO

Footer:

IF EXISTS (SELECT * FROM #tmpErrors) ROLLBACK TRANSACTION
GO
IF @@TRANCOUNT>0 BEGIN
    PRINT 'Script succeeded'
    COMMIT TRANSACTION
END
ELSE BEGIN 
    PRINT 'Script failed'
END
GO
DROP TABLE #tmpErrors

Wrapper (For each database object):

/* Insert Data Definition here then append with...*/
GO
IF @@ERROR<>0 AND @@TRANCOUNT>0 ROLLBACK TRANSACTION
GO
IF @@TRANCOUNT=0 BEGIN INSERT INTO #tmpErrors (Error) SELECT 1 BEGIN TRANSACTION END
GO
Aethyrial
A: 

Red Gate's SQL Compare will do it for you, it is a great tool.

AlexKuznetsov