データベースのコピーを作成するときは、常に新しい空のデータベースを作成してから、既存のデータベースのバックアップをそのデータベースに復元します。しかし、これが本当にエラーが発生しにくく、複雑でなく、最も効率的な方法であるかどうか疑問に思っています。
5 に答える
空のデータベースを作成するステップをスキップすることができます。復元プロセスの一部として、新しいデータベースを作成できます。
これは実際、私が知っているデータベースを複製する最も簡単で最良の方法です。SQL Server Management Studio を介して実行するのではなく、バックアップと復元のプロセスをスクリプト化することで、エラーを排除できます。
他に 2 つのオプションがあります。
- データベースをデタッチし、.mdf ファイルをコピーして再アタッチします。
- SQL Server Integration Services (SSIS) を使用して、すべてのオブジェクトをコピーします。
バックアップと復元に固執し、必要に応じて自動化することをお勧めします。
これは、私が過去に使用した動的 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)
バックアップと復元は、私が知っている最も簡単な方法です。復元されたデータベースにはセキュリティ資格情報が付属していないため、サーバー間で注意する必要があります。
::================ 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
Publish to Provider機能は、私にとって非常にうまく機能しました。Scott Gu のブログ エントリを参照してください。
本当に堅牢なものが必要な場合は、ここで redgate ソフトウェアのツールを参照してください...多くの SQL をまったく実行している場合、これらは $$ の価値があります。