Question

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. The server I have restored the database to has all the logins defined, however they have different sids.

I am not a T-SQL expert….

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.

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. 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.)

 45  92890  45
1 Jan 1970

Solution

 43

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.

2009-05-15

Solution

 29

I came up with the following. It works great because it shows you:

  1. All the current orphaned users.
  2. Which ones were fixed.
  3. Which ones couldn't be fixed.

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.

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:

enter image description here

*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.

2012-05-31