[英]Linking ALL Users to Login after restoring a SQL Server 2005 database
(Note this question asks about linking ALL Users, unlike the possible duplicate that asks about linking a single user) (注意这个问题询问链接所有用户,不像询问链接单个用户的可能重复)
I wish to move a database between two servers, I have backed the database up from the first server and done a database restore on the 2nd server, so far so good.我希望在两台服务器之间移动数据库,我已经从第一台服务器备份了数据库并在第二台服务器上进行了数据库恢复,到目前为止一切顺利。
However our application makes use of a lot of database users that are defined in the database.然而,我们的应用程序使用了许多在数据库中定义的数据库用户。 These have to be linked to logins that are defined in the master database.
这些必须链接到在 master 数据库中定义的登录名。 The server I have restored the database to has all the logins defined, however they have different sids.
我将数据库恢复到的服务器定义了所有登录名,但是它们具有不同的 sid。
I am not a T-SQL expert….我不是 T-SQL 专家……
I think sp_change_users_login
is part of the solution, but I can't find out how to get it to automatically link all users in the restored database to the login of the same name.我认为
sp_change_users_login
是解决方案的一部分,但我不知道如何让它自动将恢复的数据库中的所有用户链接到同名登录。
The database creation scripts we use for our application create the users and logins, however it does not specify the SID when creating the login, hence this problem.我们用于应用程序的数据库创建脚本创建了用户和登录名,但是它在创建登录名时没有指定 SID,因此出现了这个问题。 Now if I had a time machine...
现在如果我有一台时光机......
(When I Google I get lots of hits, however they are mostly sites that won't let you see the answer without having to register on the site first.) (当我谷歌时,我得到了很多点击,但是它们大多是网站,如果您不必先在网站上注册,就不会让您看到答案。)
Yes, you can do that by executing:是的,您可以通过执行:
EXEC sp_change_users_login 'Auto_Fix' , 'TheUserName';
However if your question was can I fix all users automatically then this won't do that.但是,如果您的问题是我可以自动修复所有用户,那么这不会这样做。
I came up with the following.我想出了以下内容。 It works great because it shows you:
它非常有效,因为它向您展示了:
Other solutions require you to know the orphaned user name before hand in order to fix.其他解决方案要求您事先知道孤立的用户名才能进行修复。
The following code could run in a sproc that is called after restoring a database to another server.以下代码可以在将数据库还原到另一台服务器后调用的 sproc 中运行。
Script:脚本:
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.
Result:结果:
*Note: The 4 that were not fixed (in my example screenshot above) did not have a corresponding User in the destination Server that the database was restored to. *注意:未修复的 4 个(在我上面的示例屏幕截图中)在数据库恢复到的目标服务器中没有相应的用户。
If:如果:
EXEC sp_change_users_login 'Auto_Fix' , 'TheUserName';
Doest't work, try this:不行,试试这个:
EXEC sp_change_users_login 'Auto_Fix', 'Username', NULL, 'p@ssword123'
I found it here: http://dbadiaries.com/using-sp_change_users_login-to-fix-sql-server-orphaned-users我在这里找到它: http : //dbadiaries.com/using-sp_change_users_login-to-fix-sql-server-orphaned-users
List of all orphan user details with corresponding DB name具有相应数据库名称的所有孤立用户详细信息的列表
Simple step简单的步骤
EXEC master.sys.sp_MSforeachdb ' USE [?]
Select ''?''
EXEC ?.dbo.sp_change_users_login ''report'' '
I found the following script from Microsoft KB918992 - run it on the original server and it will create a stored procedure called 'sp_help_revlogin' which generates another script to run on the destination server, creating all user accounts with the same passwords and sids.我从Microsoft KB918992 中找到了以下脚本 - 在原始服务器上运行它,它将创建一个名为“sp_help_revlogin”的存储过程,它生成另一个脚本以在目标服务器上运行,使用相同的密码和 sid 创建所有用户帐户。 Worked wonders for our upgrade from SQL2000 to 2008.
为我们从 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
I have a nice script that you can use to create logins from database users,which I came across after searching for this issue this script is using a stored procedure.我有一个很好的脚本,您可以使用它从数据库用户创建登录名,这是我在搜索此问题后遇到的,该脚本使用的是存储过程。 you can find some other useful scripts here also at this url http://www.sqlserveroptimizer.com/2011/08/how-to-script-logins-from-user-database-in-sql-server-20052008-r2/
您也可以在此网址上找到其他一些有用的脚本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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.