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

Posted

技术标签:

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

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

【问题讨论】:

【参考方案1】:

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

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

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

    分离数据库,复制 .mdf 文件并重新附加。 使用 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

【讨论】:

以上是关于复制数据库的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

c# 在 c# 应用程序中保存配置数据的最佳方法是啥。 [复制]

将信息从 Scrapy 爬虫连续导出到 Django 应用程序数据库的最佳方法是啥? [复制]

为在线杂志设计数据库的最佳策略是啥? [复制]

SQL(Java,h2):检索我刚刚插入数据库的单个项目的唯一 ID 的最佳方法是啥? [复制]

存储银行数据的最佳数据类型是啥? [复制]

保存多语言数据的最佳数据库结构是啥? [复制]