データベースを別のサーバーに完全に再配置するのではなく、データファイルとログファイルをより多くの領域を持つ別のドライブに移動するだけです。これを行う方法について矛盾する方向を見たので、推奨される適切な方法を探しています。
use master
go
sp_detach_db 'mydb'
DECLARE @SRCData nvarchar(1000)
SET @SRCData = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\mydb.mdf';
DECLARE @SRCLog nvarchar(1000)
SET @SRCLog = N'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\mydb_log.ldf';
DECLARE @FILEPATH nvarchar(1000);
DECLARE @LOGPATH nvarchar(1000);
SET @FILEPATH = N'xcopy /Y ' + @SRCData + N' D:\Data';
SET @LOGPATH = N'xcopy /Y ' + @SRCLog + N' E:\Log';
exec xp_cmdshell @FILEPATH;
exec xp_cmdshell @LOGPATH;
sp_attach_db 'mydb', 'D:\Data\mydb.mdf', 'E:\Log\mydb_log.ldf'
詳細はこちら Microsoft KB記事 。
別の方法-データベースファイルをデタッチし(データベース->タスク->デタッチ)、それらを新しいドライブに移動してから、再度アタッチします。しかし、Jay Sによって記述された方法は最も単純です。
絶対に安全であるために、私は次のことを行います:
スクリプトのサンプル:
-- Get the file list from a backup file.
-- This will show you current logical names and paths in the BAK file
RESTORE FILELISTONLY FROM disk = N'C:\Backups\MyDatabaseName.bak'
-- Perform the restore of the database from the backup file.
-- Replace 'move' names (MDFLogicalName, LDFLogicalName) with those found in
-- the previous filelistonly command
restore database MyDatabaseName
from disk = N'C:\Backups\MyDatabaseName.bak'
with move 'MDFLogicalName' to 'D:\SQLData\MyDatabaseName.mdf',
move 'LDFLogicalName' to 'D:\SQLLogs\MyDatabaseName_log.ldf',
replace, stats=10;
メモ
最初のスクリプトは、2番目のスクリプトで必要となる現在の名前とパスを取得します。 2番目のスクリプトは、データベースを希望する名前に復元しますが、保存する場所を変更できます。上記の例では、MDFおよびLDFファイルをD:ドライブに移動します。
SQL Serverインスタンスでxp_cmdshellを有効にしたくないので、代わりにPowershellを使用してこれを行う関数を作成しました。これは、多数のデータベースを移動する必要がある場合に特に役立ちました。
function Move-Database
{
param ($database, $newPath)
$paths = Invoke-SqlCmd "SELECT master_files.physical_name as Path
FROM sys.databases
JOIN sys.master_files ON master_files.database_id = databases.database_id
WHERE databases.name = '$database';";
$paths = $paths | % { $_.Path };
if (!$paths)
{
throw "Unknown database '$database'";
}
Write-Host "Setting $database to single-user mode...";
Invoke-SqlCmd "ALTER DATABASE [$database] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;";
Write-Host "Detaching $database";
Invoke-SqlCmd "EXEC sp_detach_db '$database';";
if (!(test-path $newPath))
{
[void](mkdir $newPath);
}
$clauses = @();
foreach ($oldFile in $paths)
{
$filename = [System.IO.Path]::GetFileName($oldFile);
$newFile = [System.IO.Path]::Combine($newPath, $filename);
$clauses += "(FILENAME = `"$newFile`")";
Write-Host "Moving $oldFile to $newFile";
mv $oldFile $newFile;
}
$clauses = $clauses -join ", ";
Write-Host "Re-attaching $database";
Invoke-SqlCmd "CREATE DATABASE [$database] ON $clauses FOR ATTACH;";
Write-Host "All done!";
}
次のように使用できます。
Move-Database -database "MyDatabase" -newPath "D:\SqlData";
また、この方法は他の方法よりも少し堅牢であると思います。たとえば、データベースが多数のファイルに分割されている場合や、ログに奇妙な命名規則がある場合などはどうでしょうか。
同じサーバー内で複数のデータベースを移動する必要があったため、コマンドのコピーと貼り付けまたは再入力を回避するために、受け入れられたソリューションを少し拡張しました。これにより、データベース名を変更するだけで、1回のスクリプト実行でデータファイルを移動できます。これは、高度なコマンドが有効になっていることを前提としています。そうでない場合は、sp_configure
。データファイルとログファイルは同じディレクトリにあると見なされます。
use master
DECLARE @DBName nvarchar(50)
SET @DBName = 'YOUR_DB_NAME'
DECLARE @RC int
EXEC @RC = sp_detach_db @DBName
DECLARE @NewPath nvarchar(1000)
SET @NewPath = 'E:\Data\Microsoft SQL Server\Data\';
DECLARE @OldPath nvarchar(1000)
SET @OldPath = 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\';
DECLARE @DBFileName nvarchar(100)
SET @DBFileName = @DBName + '.mdf';
DECLARE @LogFileName nvarchar(100)
SET @LogFileName = @DBName + '_log.ldf';
DECLARE @SRCData nvarchar(1000)
SET @SRCData = @OldPath + @DBFileName;
DECLARE @SRCLog nvarchar(1000)
SET @SRCLog = @OldPath + @LogFileName;
DECLARE @DESTData nvarchar(1000)
SET @DESTData = @NewPath + @DBFileName;
DECLARE @DESTLog nvarchar(1000)
SET @DESTLog = @NewPath + @LogFileName;
DECLARE @FILEPATH nvarchar(1000);
DECLARE @LOGPATH nvarchar(1000);
SET @FILEPATH = N'xcopy /Y "' + @SRCData + N'" "' + @NewPath + '"';
SET @LOGPATH = N'xcopy /Y "' + @SRCLog + N'" "' + @NewPath + '"';
exec xp_cmdshell @FILEPATH;
exec xp_cmdshell @LOGPATH;
EXEC @RC = sp_attach_db @DBName, @DESTData, @DESTLog
go
また、SQL Serverプロセスを実行しているユーザーがフォルダーにアクセスできることを確認する必要もあります。 SQL2014の場合、デフォルトのユーザープロセスは「NT Service\MSSQL $ SQL2014」です。