web-dev-qa-db-ja.com

SQL Server 2005でデータベースをあるドライブから別のドライブに移動する適切な方法は何ですか?

データベースを別のサーバーに完全に再配置するのではなく、データファイルとログファイルをより多くの領域を持つ別のドライブに移動するだけです。これを行う方法について矛盾する方向を見たので、推奨される適切な方法を探しています。

25
Kilhoffer

データベースをデタッチします。

use master
go 
sp_detach_db 'mydb'

データベースファイルを移動します(図のxp_cmdshellからXcopy)。

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記事

27
Rich

別の方法-データベースファイルをデタッチし(データベース->タスク->デタッチ)、それらを新しいドライブに移動してから、再度アタッチします。しかし、Jay Sによって記述された方法は最も単純です。

11
Alex_L

絶対に安全であるために、私は次のことを行います:

  1. データベースをBAKファイルにバックアップします。
  2. 現在のデータベースをオフラインにするか、必要に応じて削除します。
  3. データベースを復元し、MDFおよびLDFファイルの場所を変更します。

スクリプトのサンプル:

-- 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:ドライブに移動します。

9
Jay S

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";

また、この方法は他の方法よりも少し堅牢であると思います。たとえば、データベースが多数のファイルに分割されている場合や、ログに奇妙な命名規則がある場合などはどうでしょうか。

2
Steve Rukuts

同じサーバー内で複数のデータベースを移動する必要があったため、コマンドのコピーと貼り付けまたは再入力を回避するために、受け入れられたソリューションを少し拡張しました。これにより、データベース名を変更するだけで、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
0

また、SQL Serverプロセスを実行しているユーザーがフォルダーにアクセスできることを確認する必要もあります。 SQL2014の場合、デフォルトのユーザープロセスは「NT Service\MSSQL $ SQL2014」です。

0
Kosmo