1. 先创建一个SqlServer
身份验证的登录名,并映射到数据库中。
如:创建用户 [kk] 映射到数据库 [mytest],此时数据库 [mytest]
会增加一个用户 [kk]
2. 此时再删除登录名 [kk],删除后,数据库[mytest]
将存在一个孤立用户 [kk]
3. 查看当前数据库中是否存在孤立用户
use mytest; exec sp_change_users_login @Action='Report';
4. 对于孤立用户,有两种情况:
a 不知道这些数据库用户之前的登录名或记不清楚数据库来源
b 对于数据库迁移一种情况,先迁移数据库,再迁移登录账号
第一种情况:
-- 创建登录名 use master; create login [kk] with password = '123456'; go -- 对孤立用户连接到现有的登录名 use mytest; exec sp_change_users_login @action='update_one', @usernamepattern='kk', --数据库孤立用户 @loginname='kk'; --关联到sql server登录名 go -- 也可以再次修改密码 use master go sp_password @old=null, @new='654321', @loginame='kk'; go
第二种情况:参考 如何在 SQL Server 2005 实例之间传输登录和密码
如:要创建与另一个数据库结构一样的数据库,可以导出脚本到另一台服务器中执行(其中有数据库用户)
注意:数据库用户的权限并没有随之授予,须手动再次授予权限!
在原数据库中创建存储过程:
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
执行存储过程,将生成登录名的创建脚本
EXEC sp_help_revlogin
将脚本拷贝到当前数据库孤立用户的服务器中执行(更多注意问题参考
如何在 SQL Server 2005 实例之间传输登录和密码)
CREATE LOGIN [kk] WITH PASSWORD = 0x0100FDBC7416947C56E903E945B5DF891643064BB7D16381577F HASHED, SID = 0xAE142AE3C75E9341B106B9BAA60BB0CC, DEFAULT_DATABASE = [mytest], CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF
虽然登录名和数据库用户已经存在了,但是原来数据库用户的角色身份、对象权限都没有了!
这时,在原数据库执行以下脚本,拷贝脚本到新的数据库中执行,将权限还原
(授予数据库孤立用户权限或者其他所有用户的权限都“迁移”过来)
-- 更改【此用户拥有的架构】 select s.name,p.name,'ALTER AUTHORIZATION ON SCHEMA::['+s.name+'] TO ['+p.name+']' from sys.schemas s inner join sys.database_principals p on s.principal_id=p.principal_id where s.name <> p.name -- 授予【数据库角色成员身份】权限 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'
如果【数据库用户】还有对其他对象有操作权限,另外授予(当前不列出所有权限)
至此,完成账号迁移,步骤如下:
1 数据库迁移,产生孤立用户
2 登录账号迁移,关联孤立用户
3 数据库用户权限迁移,所有操作权限重新授予
参考:
如何在
SQL Server 2005
实例之间传输登录和密码
时间: 2024-11-08 19:09:11