代码之家  ›  专栏  ›  技术社区  ›  Dan TheCodeJunkie

复制数据库的最佳方法是什么?

  •  24
  • Dan TheCodeJunkie  · 技术社区  · 17 年前

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

    5 回复  |  直到 7 年前
        1
  •  2
  •   Brett Veenstra    17 年前

    备份和恢复是我所知道的最直接的方法。您必须在服务器之间小心,因为安全凭据不会随还原的数据库一起提供。

        2
  •  6
  •   Roddy    17 年前

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

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

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

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

    我建议在必要的时候坚持备份、恢复和自动化。

        3
  •  5
  •   brendan    17 年前

    这是我过去使用过的动态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)
    
    
    
    
    
    
        4
  •  0
  •   caryden    17 年前

    这个 发布到提供程序 功能对我来说非常有用。见 Scott Gu's Blog Entry .

    如果你需要一些真正强大的东西,看看Redgate软件的工具 here …如果您要做大量的SQL,那么这些值$

        5
  •  0
  •   Yordan Georgiev    16 年前
    ::================ 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