2013年1月28日月曜日

SQL Server2000から2008への移行手順

SQL Server2000から2008にユーザ情報及びデータを移行する必要があり、その際の方法について記載しておきます。

[データベースの移行]
1.移行元であるSQL Server 2000にて、対象となるデータベースのバックアップを取得します。対象のデータベースを選択し、「すべてのタスク」→「データベースのバックアップ」を実行します。
バックアップの項目で、「データベース-全体」を選択し、出力先にバックアップ先を追加して、「OK」をクリックします。

2.作成されたファイル(ここではsample.bak)を移行先にコピーします。

3.移行先にてデータベースの復元を実行します。
復元用のソースには1の移行元からコピーしたファイルを指定し、復元するバックアップセットの選択欄の復元項目にチェックを付けて、「OK」をクリックします。
そして、復元先データベースに復元するデータベース名を選択します。

4.既に移行先のデータベースを作成済みの場合には、下記のような「バックアップセットは、既存のデータベース’sample’以外のデータベースのバックアップを保持しています。」とのエラーが表示されます。

下記のように、オプション項目の「既存のデータベースを上書きする」にチェックを付けて「OK」をクリックします。


[ログイン情報の移行]
1.移行元であるSQL Server 2000にて、下記のスクリプトを実行し、ログイン情報を取得するためのプロシージャを作成します。このスクリプトにより、master データベースに sp_hexadecimal と sp_help_revlogin という 2 つのストアド プロシージャが作成されます。



----- Begin Script, Create sp_help_revlogin procedure -----

USE master
GO
IF OBJECT_ID ('sp_hexadecimal') IS NOT NULL
  DROP PROCEDURE sp_hexadecimal
GO
CREATE PROCEDURE sp_hexadecimal
    @binvalue varbinary(256),
    @hexvalue varchar(256) OUTPUT
AS
DECLARE @charvalue varchar(256)
DECLARE @i int
DECLARE @length int
DECLARE @hexstring char(16)
SELECT @charvalue = '0x'
SELECT @i = 1
SELECT @length = DATALENGTH (@binvalue)
SELECT @hexstring = '0123456789ABCDEF'
WHILE (@i <= @length)
BEGIN
  DECLARE @tempint int
  DECLARE @firstint int
  DECLARE @secondint int
  SELECT @tempint = CONVERT(int, SUBSTRING(@binvalue,@i,1))
  SELECT @firstint = FLOOR(@tempint/16)
  SELECT @secondint = @tempint - (@firstint*16)
  SELECT @charvalue = @charvalue +
    SUBSTRING(@hexstring, @firstint+1, 1) +
    SUBSTRING(@hexstring, @secondint+1, 1)
  SELECT @i = @i + 1
END
SELECT @hexvalue = @charvalue
GO

IF OBJECT_ID ('sp_help_revlogin') IS NOT NULL
  DROP PROCEDURE sp_help_revlogin
GO
CREATE PROCEDURE sp_help_revlogin @login_name sysname = NULL AS
DECLARE @name    sysname
DECLARE @dbname    sysname
DECLARE @xstatus int
DECLARE @binpwd  varbinary (256)
DECLARE @txtpwd  sysname
DECLARE @tmpstr  varchar (256)
DECLARE @SID_varbinary varbinary(85)
DECLARE @SID_string varchar(256)

IF (@login_name IS NULL)
  DECLARE login_curs CURSOR FOR
    SELECT login.sid, login.name, login.xstatus, login.password, db.name FROM master..sysxlogins login, master..sysdatabases db
    WHERE login.srvid IS NULL AND login.dbid = db.dbid AND login.name <> 'sa'
ELSE
  DECLARE login_curs CURSOR FOR
    SELECT login.sid, login.name, login.xstatus, login.password, db.name FROM master..sysxlogins login, master..sysdatabases db
    WHERE login.srvid IS NULL AND login.dbid = db.dbid AND login.name = @login_name
OPEN login_curs
FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @xstatus, @binpwd, @dbname
IF (@@fetch_status = -1)
BEGIN
  PRINT 'No login(s) found.'
  CLOSE login_curs
  DEALLOCATE login_curs
  RETURN -1
END
SET @tmpstr = '/* sp_help_revlogin script '
PRINT @tmpstr
SET @tmpstr = '** Generated '
  + CONVERT (varchar, GETDATE()) + ' on ' + @@SERVERNAME + ' */'
PRINT @tmpstr
PRINT ''
PRINT 'DECLARE @pwd sysname'
WHILE (@@fetch_status <> -1)
BEGIN
  IF (@@fetch_status <> -2)
  BEGIN
    PRINT ''
    SET @tmpstr = '-- Login: ' + @name
    PRINT @tmpstr
    IF (@xstatus & 4) = 4
    BEGIN -- NT authenticated account/group
      IF (@xstatus & 1) = 1
      BEGIN -- NT login is denied access
        SET @tmpstr = 'EXEC master..sp_denylogin ''' + @name + ''''
        PRINT @tmpstr
      END
      ELSE BEGIN -- NT login has access
        SET @tmpstr = 'EXEC master..sp_grantlogin ''' + @name + ''''
        PRINT @tmpstr
      END
    END
    ELSE BEGIN -- SQL Server authentication
      IF (@binpwd IS NOT NULL)
      BEGIN -- Non-null password
        EXEC sp_hexadecimal @binpwd, @txtpwd OUT
        IF (@xstatus & 2048) = 2048
          SET @tmpstr = 'SET @pwd = CONVERT (varchar(256), ' + @txtpwd + ')'
        ELSE
          SET @tmpstr = 'SET @pwd = CONVERT (varbinary(256), ' + @txtpwd + ')'
        PRINT @tmpstr
EXEC sp_hexadecimal @SID_varbinary,@SID_string OUT
        SET @tmpstr = 'EXEC master..sp_addlogin ''' + @name
          + ''', @pwd, @sid = ' + @SID_string + ', @encryptopt = '
      END
      ELSE BEGIN
        -- Null password
EXEC sp_hexadecimal @SID_varbinary,@SID_string OUT
        SET @tmpstr = 'EXEC master..sp_addlogin ''' + @name
          + ''', NULL, @sid = ' + @SID_string + ', @encryptopt = '
      END
      IF (@xstatus & 2048) = 2048
        -- login upgraded from 6.5
        SET @tmpstr = @tmpstr + '''skip_encryption_old'''
      ELSE
        SET @tmpstr = @tmpstr + '''skip_encryption'''
      PRINT @tmpstr
    END
   
    PRINT 'EXEC master..sp_defaultdb ''' + @name + ''', ''' + @dbname + ''''
  END
  FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @xstatus, @binpwd, @dbname
  END
CLOSE login_curs
DEALLOCATE login_curs
RETURN 0
GO
 ----- End Script -----



2.sp_help_revlogin ストアド プロシージャを作成した後、移行元のクエリアナライザで sp_help_revlogin プロシージャを実行します。

  EXEC master..sp_help_revlogin

3.sp_help_revlogin ストアド プロシージャの出力は、元のログインと同じ SID およびパスワードを持つログインを作成するログインスクリプトです。この出力を保存し、移行先 SQL Server にて実行します。

例:
/* sp_help_revlogin script 
** Generated 01 25 2013  7:43PM on ***DB */
DECLARE @pwd sysname
-- Login: sample
SET @pwd = CONVERT (varbinary(256), 
0x999999999999999999999999ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ)
EXEC master..sp_addlogin 'sample', @pwd, @sid = 0x99999999999999ZZZZZZZZZZZZZZZZZZ, 
@encryptopt = 'skip_encryption'
EXEC master..sp_defaultdb 'sample', 'sampledb'
-- Login: BUILTIN\Administrators
EXEC master..sp_grantlogin 'BUILTIN\Administrators'
EXEC master..sp_defaultdb 'BUILTIN\Administrators', 'master'

参考にした情報はこちら
こちらの情報では、既定のデータベースを指定する形式になっていなかったので、既定のデータベースも設定するようにプロシージャを変更してあります。


[参考]
masterデータベースのデータベースの復元を実施する場合には、SQL Serverをシングルユーザモードにて起動させる必要があります。シングルユーザモードの起動方法は下記の通りです。

1.サービスから対象のSQL Serverのインスタンスを停止します。

2.コマンドプロンプトから、下記のコマンドを実行します。

  C:\Program Files\Microsoft SQL Server\MSSQL10_50.STKDWH\MSSQL\Binn\sqlservr.exe -m

これで、シングルユーザモードにて起動します。終了させる場合は、Ctrl-Cを押下することで終了します。