Blog Post

Script for database snapshot

,

The idea for this script came at a time when I was having a project that needed to use snapshots of databases frequently. For that reason I needed to create a T-SQL code that would make snapshots for me instantly. I searched the web for this, but didn’t find something that was suitable for my project works, and decided to write my own script. The script was firstly published in the SqlServerCentral repository.

/***************************************************************************
Snapshot script:
    The script enables a quick creation of snapshots for databases. 
    It has two "run modes" defined by the optional parameter @exec_mode:
      @exec_mode=0 (default) means printing the create T_SQL statement;
      @exec_mode=1 means creation of the snapshot database;
      @database is mandatory input parameter.
    
    Tested on SQL Server 2008, 2008 R2, 2012, 2014, 2016
    EXEC [dbo].[Create_UserDb_Snapshot] @database = 'AdventureWorks2014'
    EXEC [dbo].[Create_UserDb_Snapshot] @database = 'AdventureWorksDW2012', @exec_mode=0
    EXEC [dbo].[Create_UserDb_Snapshot] @database = 'AdventureWorks2014', @exec_mode=1
Date created:      2014-Mar-12
Author:            Igor Micev
***************************************************************************/USE [master];
GO
IF EXISTS(SELECT * FROM sys.objects WHERE object_id=OBJECT_ID(N'[dbo].[Create_UserDb_Snapshot]') AND [type] IN(N'P',N'PC'))
BEGIN
    DROP PROCEDURE [dbo].[Create_UserDb_Snapshot]
END;
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
CREATE PROCEDURE [dbo].[Create_UserDb_Snapshot]
@database VARCHAR(50),@exec_mode BIT=0
AS 
BEGIN
    SET NOCOUNT ON;    
    DECLARE @err_text NVARCHAR(200);
    
    IF @database IN('master','model','tempdb')
    BEGIN
        SET @err_text='Snapshot is not allowed for master, model and tempdb databases.';        
        RAISERROR(@err_text,10,1);        
        RETURN;
    END;
    
    IF OBJECT_ID('tempdb..#usr_db_files_tbl') IS NOT NULL
    BEGIN
        DROP TABLE #usr_db_files_tbl
    END;
    
    CREATE TABLE #usr_db_files_tbl (
     [logicalName] VARCHAR(100),[physicalName] VARCHAR(200)
    );
    
    INSERT INTO #usr_db_files_tbl(logicalName,physicalName)
    SELECT [mf].[name],[mf].[physical_name]
    FROM sys.master_files AS [mf]
    WHERE [mf].[database_id]=DB_ID(@database) AND [mf].[type]=0 AND [mf].[name] NOT IN('master','model','tempdb');
    
    IF(SELECT COUNT(*) FROM #usr_db_files_tbl)=0
    BEGIN
        SET @err_text='The specified database does not exist.';        
        RAISERROR(@err_text,10,1);        
        RETURN;
    END;
    
    DECLARE @dyn_sql NVARCHAR(MAX);
    DECLARE @extension VARCHAR(20)='snap'+RIGHT(REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(20),GETDATE(),113),'-',''),':',''),' ',''),4);
    DECLARE @curLogicalName VARCHAR(100),@curPhysicalName VARCHAR(200);
    DECLARE snap_cursor CURSOR FOR SELECT [t].[logicalName],[t].[physicalName]
                                   FROM #usr_db_files_tbl AS [t];
    
    OPEN snap_cursor;    
    DECLARE @snapDbName NVARCHAR(100);    
    SET @snapDbName=@database+'_SS_'+REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(20),GETDATE(),113),'-',''),':',''),' ','');
    
    FETCH NEXT FROM snap_cursor INTO @curLogicalName,@curPhysicalName;    
    SET @dyn_sql='CREATE DATABASE '+@snapDbName+' ON '+CHAR(10);
    
    WHILE(@@FETCH_STATUS=0)
    BEGIN
        SET @dyn_sql+='(name='''+@curLogicalName+''', filename='''+REPLACE(REPLACE(@curPhysicalName,RIGHT(@curPhysicalName,4),'.'+@extension),RIGHT(@curPhysicalName,4),'.'+@extension)+''')';        
        FETCH NEXT FROM snap_cursor INTO @curLogicalName,@curPhysicalName;        
        IF(@@FETCH_STATUS=0)
        BEGIN
            SET @dyn_sql+=', '+CHAR(10)
        END;
    END;
    
    SET @dyn_sql+=CHAR(10);    
    SET @dyn_sql+='AS SNAPSHOT OF '+@database+CHAR(10);
    
    IF @exec_mode=CONVERT(BIT,0)
    BEGIN
        PRINT CHAR(10)+@dyn_sql
    END;
    
    IF @exec_mode=CONVERT(BIT,1)
    BEGIN
        BEGIN TRY
            EXEC sp_executesql @dyn_sql;            
            PRINT 'Snapshot of database: '+@snapDbName+' created successfully.';
        END TRY
        BEGIN CATCH
            SET @err_text='Snapshot of database '+@database+' cannot be created.';            
            RAISERROR(@err_text,16,1);
        END CATCH;
    END;
    
    CLOSE snap_cursor;    
    DEALLOCATE snap_cursor;
    
    IF OBJECT_ID('tempdb..#usr_db_files_tbl') IS NOT NULL
    BEGIN
        DROP TABLE #usr_db_files_tbl
    END;
    
    WAITFOR DELAY '00:00:01';   
    RETURN;
END;

 

Rate

Share

Share

Rate