【问题标题】:What is the best way to copy a database?复制数据库的最佳方法是什么?
【发布时间】:2010-09-05 07:42:48
【问题描述】:

当我想复制一个数据库时,我总是创建一个新的空数据库,然后将现有数据库的备份恢复到其中。但是,我想知道这是否真的是最不容易出错、最不复杂和最有效的方法?

【问题讨论】:

    标签: sql-server sql-server-2008


    【解决方案1】:

    可以跳过创建空数据库的步骤。您可以在还原过程中创建新数据库。

    这实际上是我所知道的克隆数据库的最简单和最好的方法。您可以通过编写备份和恢复过程脚本来消除错误,而不是通过 SQL Server Management Studio 运行它

    您可以探索其他两个选项:

    1. 分离数据库,复制 .mdf 文件并重新附加。
    2. 使用 SQL Server Integration Services (SSIS) 复制所有对象

    如果需要,我建议坚持备份和恢复以及自动化。

    【讨论】:

      【解决方案2】:

      这是我过去使用过的动态 sql 脚本。它可以进一步修改,但它将为您提供基础知识。我更喜欢编写脚本以避免使用 Management Studio 时可能犯的错误:

      
      Declare @OldDB varchar(100)
      Declare @NewDB varchar(100)
      Declare @vchBackupPath varchar(255)
      Declare @query varchar(8000)
      
      
      /*Test code to implement 
      Select @OldDB = 'Pubs'
      Select @NewDB = 'Pubs2'
      Select @vchBackupPath = '\\dbserver\C$\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Backup\pubs.bak'
      */
      
      SET NOCOUNT ON;
      
      Select @query = 'Create Database ' + @NewDB
      exec(@query)
      
      Select @query = '
      Declare @vBAKPath varchar(256)
      declare @oldMDFName varchar(100)
      declare @oldLDFName varchar(100)
      declare @newMDFPath varchar(100)
      declare @newLDFPath varchar(100)
      declare @restQuery varchar(800)
      
      select @vBAKPath = ''' + @vchBackupPath + '''
      select @oldLDFName = name from ' + @OldDB +'.dbo.sysfiles where filename like ''%.ldf%''
      select @oldMDFName = name from  ' + @OldDB +'.dbo.sysfiles where filename like ''%.mdf%''
      select @newMDFPath = physical_name from ' + @NewDB +'.sys.database_files where type_desc = ''ROWS''
      select @newLDFPath = physical_name from ' + @NewDB +'.sys.database_files where type_desc = ''LOG''
      
      select @restQuery = ''RESTORE DATABASE ' + @NewDB + 
      ' FROM DISK = N'' + '''''''' + @vBAKpath + '''''''' + 
      '' WITH MOVE N'' + '''''''' + @oldMDFName + '''''''' +  
      '' TO N'' + '''''''' + @newMDFPath + '''''''' +  
      '', MOVE N'' + '''''''' + @oldLDFName + '''''''' +  
      '' TO N'' + '''''''' + @newLDFPath + '''''''' +  
      '', NOUNLOAD, REPLACE, STATS = 10''
      
      exec(@restQuery)
      --print @restQuery'
      
      
      exec(@query)
      
      
      
      
      
      

      【讨论】:

        【解决方案3】:

        备份和恢复是我所知道的最直接的方法。您必须在服务器之间小心,因为恢复的数据库不附带安全凭证。

        【讨论】:

          【解决方案4】:

          Publish to Provider 功能对我来说非常有用。见Scott Gu's Blog Entry

          如果您需要一些真正强大的东西,请查看 redgate 软件的工具 here...如果您要执行大量 SQL,这些都是值得的。

          【讨论】:

            【解决方案5】:
            ::================ BackUpAllMyDatabases.cmd ============= START
            ::BackUpAllMyDatabases.cmd
            :: COMMAND LINE BATCH SCRIPT FOR TAKING BACKUP OF ALL DATABASES 
            
            ::RUN THE SQL SCRIPT VIA THE COMMAND LINE WITH LOGGING 
            sqlcmd -S localhost -e  -i "BackUpAllMyDatabases.sql" -o Result_Of_BackUpAllMyDatabases.log
            
            ::VIEW THE RESULTS
            Result_Of_BackUpAllMyDatabases.log
            
            ::pause
            ::================ BackUpAllMyDatabases.cmd ============= END
            
            
            --=================================================BackUpAllMyDatabases.sql start
            DECLARE @DBName varchar(255)
            
            DECLARE @DATABASES_Fetch int
            
            DECLARE DATABASES_CURSOR CURSOR FOR
                select
                    DATABASE_NAME   = db_name(s_mf.database_id)
                from
                    sys.master_files s_mf
                where
                   -- ONLINE
                    s_mf.state = 0 
            
                   -- Only look at databases to which we have access
                and has_dbaccess(db_name(s_mf.database_id)) = 1 
            
                    -- Not master, tempdb or model
                --and db_name(s_mf.database_id) not in ('Master','tempdb','model')
                group by s_mf.database_id
                order by 1
            
            OPEN DATABASES_CURSOR
            
            FETCH NEXT FROM DATABASES_CURSOR INTO @DBName
            
            WHILE @@FETCH_STATUS = 0
            BEGIN
                declare @DBFileName varchar(256)    
                set @DBFileName = @DbName + '_' + replace(convert(varchar, getdate(), 112), '-', '.') + '.bak'
            --REMEMBER TO PUT HERE THE TRAILING \ FOR THE DIRECTORY !!!
                exec ('BACKUP DATABASE [' + @DBName + '] TO  DISK = N''D:\DATA\BACKUPS\' + 
                    @DBFileName + ''' WITH NOFORMAT, INIT,  NAME = N''' + 
                    @DBName + '-Full Database Backup'', SKIP, NOREWIND, NOUNLOAD,  STATS = 100')
            
                FETCH NEXT FROM DATABASES_CURSOR INTO @DBName
            END
            
            CLOSE DATABASES_CURSOR
            DEALLOCATE DATABASES_CURSOR
            
            --BackUpAllMyDatabases==========================end
            
            --======================RestoreDbFromFile.sql start
            -- Restore database from file
            -----------------------------------------------------------------
            use master
            go
            
            declare @backupFileName varchar(100), @restoreDirectory varchar(100),
            @databaseDataFilename varchar(100), @databaseLogFilename varchar(100),
            @databaseDataFile varchar(100), @databaseLogFile varchar(100),
            @databaseName varchar(100), @execSql nvarchar(1000)
            
            -- Set the name of the database to restore
            set @databaseName = 'ReplaceDataBaseNameHere'
            -- Set the path to the directory containing the database backup
            set @restoreDirectory = 'ReplaceRestoreDirectoryHere' -- such as 'c:\temp\'
            
            -- Create the backup file name based on the restore directory, the database name and today's date
            
            @backupFileName = @restoreDirectory + @databaseName + '-' + replace(convert(varchar, getdate(), 110), '-', '.') + '.bak'
            
            
            -- set @backupFileName = 'D:\DATA\BACKUPS\server.poc_test_fbu_20081016.bak'
            
            -- Get the data file and its path
            select @databaseDataFile = rtrim([Name]),
            @databaseDataFilename = rtrim([Filename])
            from master.dbo.sysaltfiles as files
            inner join
            master.dbo.sysfilegroups as groups
            on
            
            files.groupID = groups.groupID
            where DBID = (
            select dbid
            from master.dbo.sysdatabases
            where [Name] = @databaseName
            )
            
            -- Get the log file and its path
            select @databaseLogFile = rtrim([Name]),
            @databaseLogFilename = rtrim([Filename])
            from master.dbo.sysaltfiles as files
            where DBID = (
            select dbid
            from master.dbo.sysdatabases
            where [Name] = @databaseName
            )
            and
            groupID = 0
            
            print 'Killing active connections to the "' + @databaseName + '" database'
            
            -- Create the sql to kill the active database connections
            set @execSql = ''
            select @execSql = @execSql + 'kill ' + convert(char(10), spid) + ' '
            from master.dbo.sysprocesses
            where db_name(dbid) = @databaseName
            and
            DBID <> 0
            and
            spid <> @@spid
            exec (@execSql)
            
            print 'Restoring "' + @databaseName + '" database from "' + @backupFileName + '" with '
            print ' data file "' + @databaseDataFile + '" located at "' + @databaseDataFilename + '"'
            print ' log file "' + @databaseLogFile + '" located at "' + @databaseLogFilename + '"'
            
            set @execSql = '
            restore database [' + @databaseName + ']
            from disk = ''' + @backupFileName + '''
            with
            file = 1,
            move ''' + @databaseDataFile + ''' to ' + '''' + @databaseDataFilename + ''',
            move ''' + @databaseLogFile + ''' to ' + '''' + @databaseLogFilename + ''',
            norewind,
            nounload,
            replace'
            
            exec sp_executesql @execSql
            
            exec('use ' + @databaseName)
            go
            
            -- If needed, restore the database user associated with the database
            /*
            exec sp_revokedbaccess 'myDBUser'
            go
            
            exec sp_grantdbaccess 'myDBUser', 'myDBUser'
            go
            
            exec sp_addrolemember 'db_owner', 'myDBUser'
            go
            
            use master
            go
            */
            --======================RestoreDbFromFile.sql
            

            【讨论】:

              猜你喜欢
              • 2012-05-15
              • 1970-01-01
              • 2010-11-13
              • 2010-09-16
              • 2010-10-20
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多