Pages

Wednesday, April 30, 2014

Sync the Logins after Restore

One of the problems restoring a database to a new server is dealing with out of sync logins.
The link between a database user name and a server user name is the SID that is generated when the login is added to SQL Server.
There are stored procedures to sync the SID's but they have to be run for each user that is out of sync in each database.
the sp_msForEachDB system stored procedure. It is a handy procedure that will execute a batch of statements for every database on the server. The database name can be referenced in the script by using a ? as a placeholder

--First run this script to see if there are any logins that are out of sync.
DECLARE @Collation VARCHAR(100)
DECLARE @SQL VARCHAR(2000)

CREATE TABLE ##TempSync (
 DB_NME VARCHAR(50)
 ,DBUserName VARCHAR(50)
 ,SysLoginName VARCHAR(50)
 )

SELECT @Collation = CONVERT(SYSNAME, DatabasePropertyEx('master', 'Collation'))

SET @SQL = 'USE [?]
SELECT ''?'' DB_NME, A.name DBUserName,B.loginname SysLoginName 
FROM sysusers A      
JOIN master.dbo.syslogins B      
ON A.name Collate ' + @Collation + ' = B.Name       
JOIN master.dbo.sysdatabases C      ON C.Name = ''?'' WHERE issqluser = 1       AND (A.sid IS NOT NULL       AND A.sid <> 0x0)       AND suser_sname(A.sid) IS NULL       AND (C.status & 32) =0 --loading       AND (C.status & 64) =0 --pre recovery       AND (C.status & 128) =0 --recovering       AND (C.status & 256) =0 --not recovered       AND (C.status & 512) =0 --offline       AND (C.status & 1024) =0 --read only ORDER BY A.name'

INSERT INTO ##TempSync
EXEC sp_msforeachdb @SQL

SELECT *
FROM ##TempSync

DROP TABLE ##TempSync

--If the first script returns data, run this script to sync the logins.
DECLARE @Collation VARCHAR(100)
DECLARE @SQL VARCHAR(2000)

SELECT @Collation = CONVERT(SYSNAME, DatabasePropertyEx('master', 'Collation'))

SET @SQL = 'USE [?]
DECLARE @DBUserName varchar(50)
DECLARE @SysLoginName varchar(50)
DECLARE SyncDBLogins CURSOR FOR SELECT A.name DBUserName,        B.loginname SysLoginName FROM sysusers A      
JOIN master.dbo.syslogins B      ON A.name Collate ' + @Collation + 
 ' = B.Name       
JOIN master.dbo.sysdatabases C      ON C.Name = ''?'' 
WHERE issqluser = 1       AND (A.sid IS NOT NULL       AND A.sid <> 0x0)       AND suser_sname(A.sid) IS NULL       AND (C.status & 32) =0 --Loading       AND (C.status & 64) =0 --pre recovery       AND (C.status & 128) =0 --recovering       AND (C.status & 256) =0 --not recovered       AND (C.status & 512) =0 --offline       AND (C.status & 1024) =0 --read only ORDER BY A.name
OPEN SyncDBLogins
FETCH NEXT FROM SyncDBLogins INTO @DBUserName, @SysLoginName
WHILE @@FETCH_STATUS = 0 BEGIN    
EXEC sp_change_users_login ''update_one'', @DBUserName, @SysLoginName    
    FETCH NEXT FROM SyncDBLogins    INTO @DBUserName, @SysLoginName END
    CLOSE SyncDBLogins
    DEALLOCATE SyncDBLogins'

EXEC sp_msforeachdb @SQL

No comments:

Post a Comment