SQL SERVER login migration

When performing database migration, one of the main tasks is to perform login name migration.
User names can basically be migrated during database backup and restore, and the mapping relationship and permissions remain unchanged before and after migration.
Login names, etc. can be migrated during the backup and restore of the master database, but because the master is used as a system library, it stores a lot of system information of the original server. After the master library is restored, the original server information will be migrated synchronously, which will cause problems with the existing server information. Conflicts, a lot of extra work needs to be done to remove the impact.
At this time, if you can use a script to migrate the login name, it will greatly facilitate our work.
There are already powerful gods on the Internet who have shared the stored procedures for migrating login names and passwords early. The stored procedure script will be attached at the end of the article. I don't know which great god wrote it first, and I can't find the original article.
However, this stored procedure can only migrate login names and passwords, and server roles cannot be migrated. Therefore, after migrating login names, server roles, users and permissions must be migrated together. Many examples on the Internet are not uniformly explained.
Use the following script to view the server roles of a login, and migrate the server roles together after the login is migrated.

--查看登录名服务器角色
SELECT sp.name AS [login_name]  
,CASE WHEN sp.[type]='S' THEN 'SQL 登录名'    
    WHEN sp.[type]='U' THEN 'Windows 登录名'    
    WHEN sp.[type]='G' THEN 'Windows 组'    
    WHEN sp.[type]='R' THEN '服务器角色'    
    WHEN sp.[type]='C' THEN '映射到证书的登录名'    
    WHEN sp.[type]='K' THEN '映射到非对称密钥的登录名'    
END AS [principal_type]  
,sp.is_disabled  
,ISNULL(sp.default_database_name,'') as [default_database_name]  
,ISNULL(rsp.name,'') AS [server_role]    
,STUFF((SELECT ','+permission_name FROM sys.server_permissions spp where sp.principal_id=spp.grantee_principal_id for xml path('')),1,1,'') as [permissions]  
FROM sys.server_principals sp     
LEFT JOIN sys.server_role_members srm ON sp.principal_id=srm.member_principal_id     
LEFT JOIN sys.server_principals rsp ON srm.role_principal_id=rsp.principal_id   
where rsp.name  is not null
ORDER BY [principal_type],sp.principal_id 
--授权服务器角色
select N'EXEC sp_addsrvrolemember  N''' +sp.name+ ''' ,N''' + rsp.name+''' '
FROM sys.server_principals sp     
LEFT JOIN sys.server_role_members srm ON sp.principal_id=srm.member_principal_id     
LEFT JOIN sys.server_principals rsp ON srm.role_principal_id=rsp.principal_id   
where rsp.name  is not null

--  将登录名添加为某个服务器级角色的成员  
EXEC sp_addsrvrolemember @loginame= 'kk' ,@rolename = 'sysadmin' 
master库中的用户名及权限可以用如下脚本进行迁移。
--  授予【数据库角色成员身份】权限  
SELECT 'exec sp_addrolemember N'''+g.name+''', N'''+u.name+''''  
FROM sys.database_principals u  
inner join sys.database_role_members m on u.principal_id = m.member_principal_id  
inner join sys.database_principals g on g.principal_id = m.role_principal_id  
ORDER BY g.name,u.name  
--  授予【安全对象】权限  
SELECT N'grant '+B.permission_name  collate chinese_prc_ci_ai_ws+N' on ['+A.name+N'] to ['+C.name+N']'  
FROM sys.sysobjects A(NOLOCK)   
INNER JOIN sys.database_permissions B(NOLOCK) ON A.id=B.major_id   
INNER JOIN sys.database_principals C(NOLOCK) ON B.grantee_principal_id=C.principal_id  
--WHERE C.name='kk' --A.name='objectName'  

After all database migrations are completed, there should be an operation to check the database user name, that is, to find out whether there are orphaned users in the database. Orphaned user, as the name implies, the user is orphaned, and there is no mapping relationship with the login name. There are generally two reasons for this. First: the user does not have a corresponding login name, and the login name is lost. Second: in the database migration process, the database is migrated first, and then the login name is migrated. At this time, the mapping relationship between the login name and the user is lost.
Orphaned users cannot use the database. Even if the corresponding login name exists, it cannot be used without the mapping relationship.
This problem can be solved with the following script:

--查看当前数据库中是否存在孤立用户(只有用户,没有对应的登录名)
exec sp_change_users_login @action='Report'

--  对孤立用户连接到现有的登录名  
use mytest;  
exec sp_change_users_login   
    @action='update_one',   
    @usernamepattern='kk', --数据库孤立用户  
    @loginname='kk'; --关联到sql server登录名  
go  

Next, attach the stored procedure script:

  EXEC sp_help_revlogin  --获取生成登录名的创建脚本

--存储过程脚本:
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 (514) OUTPUT  
AS  
DECLARE @charvalue varchar (514)  
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 @type varchar (1)  
DECLARE @hasaccess int  
DECLARE @denylogin int  
DECLARE @is_disabled int  
DECLARE @PWD_varbinary  varbinary (256)  
DECLARE @PWD_string  varchar (514)  
DECLARE @SID_varbinary varbinary (85)  
DECLARE @SID_string varchar (514)  
DECLARE @tmpstr  varchar (1024)  
DECLARE @is_policy_checked varchar (3)  
DECLARE @is_expiration_checked varchar (3)  

DECLARE @defaultdb sysname  

IF (@login_name IS NULL)  
  DECLARE login_curs CURSOR FOR  

      SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM   
sys.server_principals p LEFT JOIN sys.syslogins l  
      ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name <> 'sa'  
ELSE  
  DECLARE login_curs CURSOR FOR  


      SELECT p.sid, p.name, p.type, p.is_disabled, p.default_database_name, l.hasaccess, l.denylogin FROM   
sys.server_principals p LEFT JOIN sys.syslogins l  
      ON ( l.name = p.name ) WHERE p.type IN ( 'S', 'G', 'U' ) AND p.name = @login_name  
OPEN login_curs  

FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin  
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 ''  
WHILE (@@fetch_status <> -1)  
BEGIN  
  IF (@@fetch_status <> -2)  
  BEGIN  
    PRINT ''  
    SET @tmpstr = '-- Login: ' + @name  
    PRINT @tmpstr  
    IF (@type IN ( 'G', 'U'))  
    BEGIN -- NT authenticated account/group  

      SET @tmpstr = 'CREATE LOGIN ' + QUOTENAME( @name ) + ' FROM WINDOWS WITH DEFAULT_DATABASE = [' + @defaultdb + ']'  
    END  
    ELSE BEGIN -- SQL Server authentication  
        -- obtain password and sid  
            SET @PWD_varbinary = CAST( LOGINPROPERTY( @name, 'PasswordHash' ) AS varbinary (256) )  
        EXEC sp_hexadecimal @PWD_varbinary, @PWD_string OUT  
        EXEC sp_hexadecimal @SID_varbinary,@SID_string OUT  

        -- obtain password policy state  
        SELECT @is_policy_checked = CASE is_policy_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name  
        SELECT @is_expiration_checked = CASE is_expiration_checked WHEN 1 THEN 'ON' WHEN 0 THEN 'OFF' ELSE NULL END FROM sys.sql_logins WHERE name = @name  

            SET @tmpstr = 'CREATE LOGIN ' + QUOTENAME( @name ) + ' WITH PASSWORD = ' + @PWD_string + ' HASHED, SID = ' + @SID_string + ', DEFAULT_DATABASE = [' + @defaultdb + ']'  

        IF ( @is_policy_checked IS NOT NULL )  
        BEGIN  
          SET @tmpstr = @tmpstr + ', CHECK_POLICY = ' + @is_policy_checked  
        END  
        IF ( @is_expiration_checked IS NOT NULL )  
        BEGIN  
          SET @tmpstr = @tmpstr + ', CHECK_EXPIRATION = ' + @is_expiration_checked  
        END  
    END  
    IF (@denylogin = 1)  
    BEGIN -- login is denied access  
      SET @tmpstr = @tmpstr + '; DENY CONNECT SQL TO ' + QUOTENAME( @name )  
    END  
    ELSE IF (@hasaccess = 0)  
    BEGIN -- login exists but does not have access  
      SET @tmpstr = @tmpstr + '; REVOKE CONNECT SQL TO ' + QUOTENAME( @name )  
    END  
    IF (@is_disabled = 1)  
    BEGIN -- login is disabled  
      SET @tmpstr = @tmpstr + '; ALTER LOGIN ' + QUOTENAME( @name ) + ' DISABLE'  
    END  
    PRINT @tmpstr  
  END  

  FETCH NEXT FROM login_curs INTO @SID_varbinary, @name, @type, @is_disabled, @defaultdb, @hasaccess, @denylogin  
   END  
CLOSE login_curs  
DEALLOCATE login_curs  
RETURN 0  
GO  

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324676913&siteId=291194637