在还原SQL Server 2005数据库之后将用户链接到login

我希望在两台服务器之间移动一个数据库,我已经从第一台服务器上备份了数据库,并在第二台服务器上完成了数据库还原,到目前为止还是不错的。

然而,我们的应用程序使用了数据库中定义的大量数据库用户。 这些必须链接到master数据库中定义的login名。 我已经恢复数据库的服务器已经定义了所有的login,但是他们有不同的sids。

我不是一个T-SQL专家。

我认为sp_change_users_login是解决scheme的一部分,但我找不到如何让它自动链接恢复数据库中的所有用户到同名的login名。

我们为我们的应用程序使用的数据库创build脚本创build用户和login,但创buildlogin时不指定SID,因此出现此问题。 现在如果我有时间机器…

(当我谷歌我得到很多点击,但他们大多是网站,不会让你看到的答案,而不必先注册在网站上。)

这种现象被称为“孤儿用户”。

这里有一篇关于它的文章以及如何解决它:

http://sqlblog.com/blogs/eric_johnson/archive/2008/10/17/fixing-orphaned-users.aspx

这里是关于命令的Books Online文章:

http://msdn.microsoft.com/en-us/library/aa259633(SQL.80).aspx

是的,你可以通过执行:

 EXEC sp_change_users_login 'Auto_Fix' , 'TheUserName'; 

但是,如果你的问题是我可以自动修复所有用户,那么这不会做到这一点。

我想出了以下几点。 它很好,因为它显示你:

  1. 目前所有的孤儿用户。
  2. 哪些是固定的。
  3. 哪些是不能修复的

其他解决scheme需要您先了解孤立的用户名,才能解决问题。

以下代码可以在将数据库还原到另一台服务器之后调用的sproc中运行。

脚本:

 EXEC sp_change_users_login 'report'--See all orphaned users in the database. DECLARE @OrphanedUsers TABLE ( IndexKey Int IDENTITY(1,1) PRIMARY KEY, UserName SysName,--nVarChar(128) UserSID VarBinary(85) ) INSERT INTO @OrphanedUsers EXEC sp_change_users_login 'report' DECLARE @CRLF as nVarChar SET @CRLF = CHAR(10) + '&' + CHAR(13)--NOTE: Carriage-Return/Line-Feed will only appear in PRINT statements, not SELECT statements. DECLARE @Sql as nVarChar(MAX) SET @Sql = N'' DECLARE @IndexKey as Int SET @IndexKey = 1 DECLARE @MaxIndexKey as Int SET @MaxIndexKey = (SELECT COUNT(*) FROM @OrphanedUsers) DECLARE @Count as Int SET @Count = 0 DECLARE @UsersFixed as nVarChar(MAX) SET @UsersFixed = N'' DECLARE @UserName as SysName--This is an orphaned Database user. WHILE (@IndexKey <= @MaxIndexKey) BEGIN SET @UserName = (SELECT UserName FROM @OrphanedUsers WHERE IndexKey = @IndexKey) IF 1 = (SELECT COUNT(*) FROM sys.server_principals WHERE Name = @UserName)--Look for a match in the Server Logins. BEGIN SET @Sql = @Sql + 'EXEC sp_change_users_login ''update_one'', [' + @UserName + '], [' + @UserName + ']' + @CRLF SET @UsersFixed = @UsersFixed + @UserName + ', ' SET @Count = @Count + 1 END SET @IndexKey = @IndexKey + 1 END PRINT @Sql EXEC sp_executesql @Sql PRINT 'Total fixed: ' + CAST(@Count as VarChar) + '. Users Fixed: ' + @UsersFixed SELECT ('Total fixed: ' + CAST(@Count as VarChar) + '. Users Fixed: ' + @UsersFixed)[Fixed] EXEC sp_change_users_login 'report'--See all orphaned users still in the database. 

结果:

在这里输入图像说明

*注:这4个不是固定的(在我上面的示例屏幕截图中)在数据库恢复到的目标服务器中没有相应的用户。

我有一个很好的脚本,可以用来创build数据库用户login,我遇到这个脚本正在使用存储过程search这个问题后遇到。 你可以在这个urlfind其他一些有用的脚本:http://www.sqlserveroptimizer.com/2011/08/how-to-script-logins-from-user-database-in-sql-server-20052008-r2/

 USE MyDatabaseName DECLARE @login nvarchar(50) DECLARE logins_cursor CURSOR FOR SELECT l.name FROM sys.database_principals u INNER JOIN sys.server_principals l ON u.sid=l.sid OPEN logins_cursor FETCH NEXT FROM logins_cursor INTO @login WHILE @@FETCH_STATUS = 0 BEGIN EXEC sp_help_revlogin @login FETCH NEXT FROM logins_cursor INTO @login END CLOSE logins_cursor DEALLOCATE logins_cursor GO 

如果:

 EXEC sp_change_users_login 'Auto_Fix' , 'TheUserName'; 

不要工作,试试这个:

 EXEC sp_change_users_login 'Auto_Fix', 'Username', NULL, 'p@ssword123' 

我在这里find它: http : //dbadiaries.com/using-sp_change_users_login-to-fix-sql-server-orphaned-users

我从Microsoft KB918992中find了以下脚本 – 在原始服务器上运行它,它将创build一个名为“sp_help_revlogin”的存储过程,该过程生成另一个脚本以在目标服务器上运行,使用相同的密码和sids创build所有用户帐户。 我们从SQL2000升级到2008,创造了奇迹。

 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 @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 sid, name, xstatus, password FROM master..sysxlogins WHERE srvid IS NULL AND name <> 'sa' ELSE DECLARE login_curs CURSOR FOR SELECT sid, name, xstatus, password FROM master..sysxlogins WHERE srvid IS NULL AND name = @login_name OPEN login_curs FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @xstatus, @binpwd 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 END FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @xstatus, @binpwd END CLOSE login_curs DEALLOCATE login_curs RETURN 0 GO