Technical Article

Database File Move Etc

,

  • Deploy into master database
  • Run in the master database
  • Usage
  • @CommentCommands (Optional (Default 1)) 1 = Commands are commented, 0 = No comments (Easier to cut and paste)
  • @GenerateAttachDetach (Optional (Default 0)) 1 = Generates attach and detach commands, 0 = Does not generate commands
  • @DataPath & @TrnPath are the new paths for the relevant database files
EXEC generatefilemove @DataPath = 'D:\', @TrnPath = 'E:\',@DatabaseName = '<DatabaseName>',@CommentCommands = 0,@GenerateAttachDetach = 0
--Deploy into master database
--Run in the master database

--Usage
-- @CommentCommands (Optional (Default 1)) 1 = Commands are commented, 0 = No comments (Easier to cut and paste)
-- @GenerateAttachDetach (Optional (Default 0)) 1 = Generates attach and detach commands, 0 = Does not generate commands
-- @DataPath & @TrnPath are the new paths for the relevant database files
-- EXEC generatefilemove @DataPath = 'D:\', @TrnPath = 'E:\',@DatabaseName = '<DatabaseName>',@CommentCommands = 0,@GenerateAttachDetach = 0


IF EXISTS ( SELECT  *
            FROM    sys.objects
            WHERE   object_id = OBJECT_ID(N'[dbo].[GenerateFileMove]')
                    AND type IN ( N'P', N'PC' ) ) 
    DROP PROCEDURE [dbo].[GenerateFileMove]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[GenerateFileMove]
    (
      @DataPath NVARCHAR(50) ,
      @TrnPath NVARCHAR(50) ,
      @DatabaseName NVARCHAR(50) ,
      @CommentCommands BIT = 1 ,
      @GenerateAttachDetach BIT = 0
    )
AS 
    BEGIN
        SET NOCOUNT ON
        DECLARE @DatabaseID INT
        DECLARE @AttachString NVARCHAR(MAX)
        
        SELECT  @DatabaseID = database_id
        FROM    master.sys.databases AS d
        WHERE   name = @DatabaseName
        
        IF @DatabaseID IS NULL 
            BEGIN
                SELECT  'Could not find the database you specified' AS 'A friendly message'
                RETURN
            END
        
        IF ( SELECT COUNT(*)
             FROM   sys.master_files AS mf
             WHERE  RIGHT(physical_name,
                          CHARINDEX('\', REVERSE(physical_name)) - 1) IN (
                    SELECT  RIGHT(physical_name,
                                  CHARINDEX('\', REVERSE(physical_name)) - 1) AS DatabaseFile
                    FROM    sys.master_files AS mf
                    WHERE   database_id = @DatabaseID )
                    AND mf.database_id <> @DatabaseID
           ) > 0 
            BEGIN
                SELECT  'Another database has the same file names as '
                        + UPPER(@DatabaseName) AS [You Really Should Read This Warning!!!]
                UNION ALL
                SELECT  'Exercise caution if moving these files to a new location'
                UNION ALL
                SELECT  'Consider renaming the files!!!'
                UNION ALL
                SELECT  'The database(s) in question are:'
                UNION ALL
                SELECT  DISTINCT
                        DB_NAME(database_id)
                FROM    sys.master_files AS mf
                WHERE   RIGHT(physical_name,
                              CHARINDEX('\', REVERSE(physical_name)) - 1) IN (
                        SELECT  RIGHT(physical_name,
                                      CHARINDEX('\', REVERSE(physical_name))
                                      - 1) AS DatabaseFile
                        FROM    sys.master_files AS mf
                        WHERE   database_id = @DatabaseID )
                        AND mf.database_id <> @DatabaseID
        
            END
        
        IF @GenerateAttachDetach = 1 
            BEGIN
                SET @AttachString = CASE WHEN @CommentCommands = 1 THEN '-- '
                                         ELSE ''
                                    END + 'CREATE DATABASE [' + @DatabaseName
                    + '] ON '

                SELECT  @AttachString = @AttachString + DatabaseFile
                FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY FILE_ID ASC ) AS FileNumber ,
                                    '( FILENAME = N'''
                                    + CASE type
                                        WHEN 0 THEN @DataPath
                                        ELSE @TrnPath
                                      END + RIGHT(physical_name,
                                                  CHARINDEX('\',
                                                            REVERSE(physical_name))
                                                  - 1) + ''' ),' AS DatabaseFile
                          FROM      sys.master_files AS mf
                          WHERE     database_id = @DatabaseID
                        ) d
                ORDER BY FileNumber ASC
            END
            

        SELECT  '-------------------------------------------- ['
                + UPPER(@DatabaseName)
                + '] --------------------------------------------'
        UNION ALL
        SELECT  '-- Move to ' + @DataPath + ' Drive'
        UNION ALL
        SELECT  '-- ' + physical_name
        FROM    sys.master_files
        WHERE   database_id = @DatabaseID
                AND type = 0
        UNION ALL
        SELECT  ''
        UNION ALL
        SELECT  '-- Move to ' + @TrnPath + ' Drive'
        UNION ALL
        SELECT  '-- ' + physical_name
        FROM    sys.master_files
        WHERE   database_id = @DatabaseID
                AND type = 1
        UNION ALL
        SELECT  ''
        UNION ALL
        SELECT  CASE WHEN @CommentCommands = 1 THEN '-- '
                     ELSE ''
                END + 'ROBOCOPY "' + LEFT(physical_name,
                                          LEN(physical_name) - CHARINDEX('\',
                                                              REVERSE(physical_name)))
                + '" "' + @DataPath + '" "' + RIGHT(physical_name,
                                                    CHARINDEX('\',
                                                              REVERSE(physical_name))
                                                    - 1) + '" /Z /MOV /XO /XN'
        FROM    sys.master_files
        WHERE   database_id = @DatabaseID
                AND type = 0
        UNION ALL
        SELECT  CASE WHEN @CommentCommands = 1 THEN '-- '
                     ELSE ''
                END + 'ROBOCOPY "' + LEFT(physical_name,
                                          LEN(physical_name) - CHARINDEX('\',
                                                              REVERSE(physical_name)))
                + '" "' + @TrnPath + '" "' + RIGHT(physical_name,
                                                   CHARINDEX('\',
                                                             REVERSE(physical_name))
                                                   - 1) + '" /Z /MOV /XO /XN'
        FROM    sys.master_files
        WHERE   database_id = @DatabaseID
                AND type = 1
        UNION ALL
        SELECT  ''
        UNION ALL
        SELECT  CASE WHEN @CommentCommands = 1 THEN '-- '
                     ELSE ''
                END + 'ALTER DATABASE [' + DB_NAME(database_id)
                + '] MODIFY FILE (NAME = [' + name + '], FILENAME = '''
                + @DataPath + RIGHT(physical_name,
                                    CHARINDEX('\', REVERSE(physical_name)) - 1)
                + ''')'
        FROM    sys.master_files
        WHERE   database_id = @DatabaseID
                AND type = 0
        UNION ALL
        SELECT  CASE WHEN @CommentCommands = 1 THEN '-- '
                     ELSE ''
                END + 'ALTER DATABASE [' + DB_NAME(database_id)
                + '] MODIFY FILE (NAME = [' + name + '], FILENAME = '''
                + @TrnPath + RIGHT(physical_name,
                                   CHARINDEX('\', REVERSE(physical_name)) - 1)
                + ''')'
        FROM    sys.master_files
        WHERE   database_id = @DatabaseID
                AND type = 1
        UNION ALL
        SELECT  ''
        UNION ALL
        SELECT  CASE WHEN @GenerateAttachDetach = 1 THEN '-- Detach Script --'
                     ELSE ''
                END
        UNION ALL
        SELECT  CASE WHEN @GenerateAttachDetach = 1
                     THEN CASE WHEN @CommentCommands = 1 THEN '-- '
                               ELSE ''
                          END + 'ALTER DATABASE [' + @DatabaseName
                          + '] SET  SINGLE_USER WITH ROLLBACK IMMEDIATE'
                     ELSE ''
                END
        UNION ALL
        SELECT  CASE WHEN @GenerateAttachDetach = 1
                     THEN CASE WHEN @CommentCommands = 1 THEN '-- '
                               ELSE ''
                          END + 'EXEC master.dbo.sp_detach_db @dbname = N'''
                          + @DatabaseName + ''''
                     ELSE ''
                END
        UNION ALL
        SELECT  ''
        UNION ALL
        SELECT  CASE WHEN @GenerateAttachDetach = 1 THEN '-- Attach Script --'
                     ELSE ''
                END
        UNION ALL
        SELECT  CASE WHEN @GenerateAttachDetach = 1
                     THEN LEFT(@AttachString, LEN(@AttachString) - 1)
                          + ' FOR ATTACH'
                     ELSE ''
                END

    END        
GO

Rate

4 (3)

You rated this post out of 5. Change rating

Share

Share

Rate

4 (3)

You rated this post out of 5. Change rating