(Notez que cette question demande de lier TOUS les utilisateurs, contrairement au double possible qui demande de lier un seul utilisateur)
Je souhaite déplacer une base de données entre deux serveurs, j'ai sauvegardé la base de données à partir du premier serveur et effectué une restauration de base de données sur le 2ème serveur, jusqu'à présent tout va bien.
Cependant, notre application utilise un grand nombre d'utilisateurs de base de données définis dans la base de données. Ceux-ci doivent être liés aux connexions définies dans la base de données master. Le serveur sur lequel j'ai restauré la base de données a toutes les connexions définies, mais elles ont des sids différents.
Je ne suis pas un expert T-SQL….
Je pense sp_change_users_login
fait partie de la solution, mais je ne peux pas trouver comment le lier automatiquement tous les utilisateurs de la base de données restaurée à la connexion du même nom.
Les scripts de création de base de données que nous utilisons pour notre application créent les utilisateurs et les connexions, mais il ne spécifie pas le SID lors de la création de la connexion, d'où ce problème. Maintenant, si j'avais une machine à voyager dans le temps ...
(Lorsque je Google, je reçois beaucoup de visites, mais ce sont principalement des sites qui ne vous laisseront pas voir la réponse sans avoir à vous inscrire d'abord sur le site.)
J'ai trouvé ce qui suit. Cela fonctionne très bien car il vous montre:
D'autres solutions nécessitent que vous connaissiez le nom d'utilisateur orphelin au préalable afin de corriger.
Le code suivant peut s'exécuter dans un sproc appelé après la restauration d'une base de données sur un autre serveur.
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.
Résultat:
* Remarque: les 4 qui n'ont pas été corrigés (dans mon exemple de capture d'écran ci-dessus) n'avaient pas d'utilisateur correspondant dans le serveur de destination sur lequel la base de données a été restaurée.
Oui, vous pouvez le faire en exécutant:
EXEC sp_change_users_login 'Auto_Fix' , 'TheUserName';
Cependant, si votre question était, puis-je résoudre tous les utilisateurs automatiquement, cela ne le fera pas.
Si:
EXEC sp_change_users_login 'Auto_Fix' , 'TheUserName';
Ne fonctionne pas, essayez ceci:
EXEC sp_change_users_login 'Auto_Fix', 'Username', NULL, 'p@ssword123'
Je l'ai trouvé ici: http://dbadiaries.com/using-sp_change_users_login-to-fix-sql-server-orphaned-users
J'ai un joli script que vous pouvez utiliser pour créer des connexions à partir d'utilisateurs de base de données, que j'ai rencontré après avoir recherché ce problème, ce script utilise une procédure stockée. vous pouvez trouver d'autres scripts utiles ici également à cette url 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
J'ai trouvé le script suivant à partir de Microsoft KB918992 - exécutez-le sur le serveur d'origine et il créera une procédure stockée appelée 'sp_help_revlogin' qui génère un autre script à exécuter sur le serveur de destination, créant tous les comptes d'utilisateurs avec le mêmes mots de passe et sids. A fait des merveilles pour notre mise à niveau de 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