Sometimes it’s handy to be able to quickly revert to a previous version of a database. During testing, it’s handy to set up your test data, snapshot the database, and test over and over again without having to restage the data each time. Backups can be time-consuming in a large database. Snapshots to the rescue!
Prerequisites:
- Obviously, you’ll need to be using a version of SQL Server that supports snapshots.
- You’ll need the appropriate permissions on the database server. The fixed server “sysadmin” role will suffice, naturally.
- You’ll need the appropriate permissions on the directory(ies) where your database files are located. If not, you can always change the script to use a different directory.
Set your SSMS to output results to text (Ctrl + T) and execute the following:
SET NOCOUNT ON DECLARE @currdate VARCHAR(20) SET @currdate = CONVERT(VARCHAR(20), GETDATE(), 120) SET @currdate = REPLACE(@currdate, ':', '') SET @currdate = REPLACE(@currdate, '-', '') SET @currdate = REPLACE(@currdate, ' ', '_') SET @currdate = SUBSTRING(@currdate, 0, 14) DECLARE @SnapshotName varchar(100) DECLARE @CreateSQL VARCHAR(MAX) = '' DECLARE @RestoreSQL VARCHAR(MAX) = '' DECLARE @names table ([Name] varchar(100), [Physical_Name] varchar(200)) DECLARE @DatabaseName varchar(100) = 'DATABASE NAME GOES HERE' ------------------------ SET @SnapshotName = @DatabaseName + '-' + @currdate + '-1.ss' DELETE @names INSERT @names ([Name], [Physical_Name]) SELECT name, physical_name FROM sys.master_files WHERE type = 0 AND (database_id = DB_ID(@DatabaseName)) IF (SELECT COUNT(*) FROM @names) > 0 BEGIN SELECT @CreateSQL = @CreateSQL + 'CREATE DATABASE ' + QUOTENAME(@SnapshotName) + ' ON ' SELECT @CreateSQL = @CreateSQL + CHAR(13) + CHAR(10) + '(NAME = ' + QUOTENAME([Name]) + ', FILENAME = ''' + [Physical_Name] + '-' + @currdate + '.snap''),' FROM @names SELECT @CreateSQL = LEFT(@CreateSQL,len(@CreateSQL)-1) + CHAR(13) + CHAR(10) + 'AS SNAPSHOT OF [' + @DatabaseName + '] ' SELECT @RestoreSQL = @RestoreSQL + 'RESTORE DATABASE [' + @DatabaseName + '] FROM DATABASE_SNAPSHOT = ''' + @SnapshotName + '''; ' END PRINT '/*' PRINT @CreateSQL PRINT '*/ /*' PRINT @RestoreSQL PRINT '*/'
You’ll get an output that looks like the following (with names and locations specific to your server):
/* CREATE DATABASE [{databasename}-1.ss] ON (NAME = [{filename01}], FILENAME = '{filepath01}-20170419_0802.snap'), (NAME = [{filename02}], FILENAME = '{filepath02}-20170419_0802.snap'), (NAME = [{filename03}], FILENAME = '{filepath03}-20170419_0802.snap') AS SNAPSHOT OF [{databasename}] */ /* RESTORE DATABASE [{databasename}] FROM DATABASE_SNAPSHOT = '{databasename}-20170419_0802-1.ss'; */
Nothing will actually execute yet. I leave that up to you.
Be careful. Don’t play with snapshots unless you understand the possible ramifications, namely, you could inadvertently trash your databases. There’s a good article with lots more details on MSDN here: Create a Database Snapshot. Enjoy!