Sql Server は、データベース内ユーザーログイン情報と、Sql Server ログイン情報の二重構造となっています。
Sql Server で、別のサーバーにフルリストアする場合、ログインエラーが発生してしまうことになります。
当記事では、この「Sql Server 特有のログインユーザーと DBユーザーのズレ (Orphaned Users)」の解消方法を解説します。
Sql Server の孤立ユーザー (Orphaned Users) の Microsoft 公式トラブルシューティングは以下のリンクからご確認ください。
孤立したユーザーのトラブルシューティング (SQL Server)
アプリケーションから Sql Server に接続した際にエラーが発生することで、フルリストアに問題があったことに気付きます。
Microsoft.Data.SqlClient.SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0
- 接続済みの呼び出し先が一定の時間を過ぎても正しく応答しなかったため、接続できませんでした。または接続済みのホストが応答しなかったため、確立された接続は失敗しました。)
フルリストアでは Sql Server ログインユーザーを復元できていないことがわかります。
以下のコードは孤立ユーザーを検出する sql です。
SSMS にWindows認証でログインし、以下のコードで「フルリストアしたDB名」の箇所だけ変更してご活用ください。
USE [master];
GO
-- === 設定 ===
DECLARE @TargetDB NVARCHAR(128) = N'フルリストアしたDB名';
DECLARE @DefaultPassword NVARCHAR(128) = N'AnyPassword777!!'; -- 新規ログイン用任意パスワード
PRINT '=== 孤立ユーザー検出中 ===';
-- 孤立ユーザー一覧を一時テーブルに格納
IF OBJECT_ID('tempdb..#OrphanedUsers') IS NOT NULL DROP TABLE #OrphanedUsers;
CREATE TABLE #OrphanedUsers (
UserName NVARCHAR(128),
UserSID VARBINARY(85)
);
DECLARE @sql NVARCHAR(MAX);
SET @sql = N'
USE [' + @TargetDB + N'];
SELECT dp.name, dp.sid
FROM sys.database_principals dp
WHERE dp.type_desc = ''SQL_USER''
AND dp.authentication_type_desc = ''INSTANCE''
AND dp.sid NOT IN (SELECT sid FROM sys.server_principals);
';
INSERT INTO #OrphanedUsers (UserName, UserSID)
EXEC (@sql);
-- === 孤立ユーザー一覧出力 ===
IF EXISTS (SELECT 1 FROM #OrphanedUsers)
BEGIN
SELECT * FROM #OrphanedUsers;
END
ELSE
BEGIN
PRINT '孤立ユーザーは存在しません。';
END
以下のコードは孤立ユーザーを修復する sql です。
前項の sql で孤立ユーザーの存在を確認できた場合に修復を試みてください。
「フルリストアしたDB名」の箇所だけ変更してご活用ください。
USE [master];
GO
-- === 設定 ===
DECLARE @TargetDB NVARCHAR(128) = N'フルリストアしたDB名''; -- 復元したDB名
DECLARE @DefaultPassword NVARCHAR(128) = N'AnyPassword777!!'; -- 新規ログイン用任意パスワード
-- 孤立ユーザー一覧を一時テーブルに格納
IF OBJECT_ID('tempdb..#OrphanedUsers') IS NOT NULL DROP TABLE #OrphanedUsers;
CREATE TABLE #OrphanedUsers (
UserName NVARCHAR(128),
UserSID VARBINARY(85)
);
-- 孤立ユーザーを抽出
INSERT INTO #OrphanedUsers (UserName, UserSID)
EXEC('USE [' + @TargetDB + ']; EXEC sp_change_users_login ''Report'';');
-- === 修復処理 ===
DECLARE @UserName NVARCHAR(128);
DECLARE @UserSID VARBINARY(85);
DECLARE @SIDHex NVARCHAR(255);
DECLARE @sql NVARCHAR(MAX);
DECLARE user_cursor CURSOR FOR SELECT UserName, UserSID FROM #OrphanedUsers;
OPEN user_cursor;
FETCH NEXT FROM user_cursor INTO @UserName, @UserSID;
WHILE @@FETCH_STATUS = 0
BEGIN
-- SID を 0x123... の文字列に変換
SET @SIDHex = '0x' + LOWER(SUBSTRING(master.dbo.fn_varbintohexstr(@UserSID), 3, 255));
IF EXISTS (SELECT 1 FROM sys.server_principals WHERE name = @UserName)
BEGIN
-- 既存ログインに紐付け
SET @sql = 'USE [' + @TargetDB + ']; ALTER USER [' + @UserName + '] WITH LOGIN = [' + @UserName + '];';
EXEC(@sql);
END
ELSE
BEGIN
-- 新規ログイン作成 + 紐付け
SET @sql = 'CREATE LOGIN [' + @UserName + '] WITH PASSWORD = ''' + @DefaultPassword + ''', SID = ' + @SIDHex + ';';
EXEC(@sql);
SET @sql = 'USE [' + @TargetDB + ']; ALTER USER [' + @UserName + '] WITH LOGIN = [' + @UserName + '];';
EXEC(@sql);
END
FETCH NEXT FROM user_cursor INTO @UserName, @UserSID;
END
CLOSE user_cursor;
DEALLOCATE user_cursor;
PRINT '=== 孤立ユーザーの修復完了 ===';