还原数据库时,还原孤立用户

时间:2022-11-25 20:46:17

示例代码:

A. 显示登录映射的当前用户的报告 列出当前数据库的孤立用户
EXEC sp_change_users_login 'Report'; 

B. 将数据库用户映射到新的 SQL Server 登录名
在以下示例中,数据库用户与新的 SQL Server 登录名关联。数据库用户 MB-Sales 首先映射到另一个登录名,然后重新映射到登录名 MaryB。 
--Create the new login.
CREATE LOGIN MaryB WITH PASSWORD = '982734snfdHHkjj3';
GO
--Map database user MB-Sales to login MaryB.
USE AdventureWorks;
GO
EXEC sp_change_users_login 'Update_One', 'MB-Sales', 'MaryB';
GO 


C. 自动将用户映射到登录名(必要时新建一个登录名)
以下示例显示如何使用 Auto_Fix 将现有用户映射到同名的登录名,以及如何在不存在登录名 Mary 的情况下,创建密码为 B3r12-3x$098f6 的 SQL Server 登录名 Mary。USE AdventureWorks;
GO
EXEC sp_change_users_login 'Auto_Fix', 'Mary', NULL, 'B3r12-3x$098f6';
GO

----------------------------------------以上你要是能看懂应该是可以解决问题的-----------下边是晦涩的专业说明-----------------------------------------------------


在项目部署的时候,经常为了方便,直接备份还原数据库文件,如果在备份的数据库里有新建的数据库访问用户账号,还原之后不能使用,还没法删除。这样的数据库用户称为孤立用户。所谓孤立帐户,就是某个数据库的帐户只有用户名而没有登录名,这样的用户在用户库的sysusers系统表中存在,而在master数据库的syslogins中却没有对应的记录。

那如何解决这个用户的问题呢?放在哪里不管又有点碍眼。

1、最笨的解决办法:
在备份的时候就直接把新建的用户删除,这样还原的时候就是干净的,在部署的服务器上新建一个用户就可以了。

2、修复原来的用户,修复之后可以继续使用或者删除重建
在SQL里可以使用系统的存储过程sp_change_users_login来解决这个问题【sp_change_users_login 不能用于 Windows 登录名。】
sp_change_users_login [ @Action = ] 'action' [ , [ @UserNamePattern = ] 'user' ] [ , [ @LoginName = ] 'login' ] [ , [ @Password = ] 'password' ] 

使用 sp_change_users_login 将当前数据库中的数据库用户链接到 SQL Server 登录名。如果用户登录名已更改,则使用 sp_change_users_login 将用户链接到新的登录,而不会丢失用户的权限。新的 login 不能为 sa,而 user 不能为 dbo、guest 或 INFORMATION_SCHEMA 用户。

[ @Action = ] 'action'

说明过程要执行的操作。action 的数据类型为 varchar(10)。action 可具有下列值之一。

说明

Auto_Fix

将当前数据库的 sysusers 表中的用户条目链接到同名的 SQL Server 登录名。如果不存在同名的登录名,将会创建一个。检查 Auto_Fix 语句的结果,确认实际链接是否正确。在对安全性较为敏感的情况下,要避免使用 Auto_Fix。

如果使用 Auto_Fix 时登录名尚不存在,则必须指定 user 和 password,否则必须指定 user,但 password 将被忽略。login 必须为 NULL。user 必须是当前数据库中的有效用户。不能将另一个用户映射到该登录名。

Report

列出当前数据库中未链接到任何登录名的用户以及相应的安全标识符 (SID)。user、login 和 password 必须为 NULL 或不指定。

Update_One

将当前数据库中的指定 user 链接到现有 SQL Server login。必须指定 user 和 login。password 必须为 NULL 或不指定。

[ @UserNamePattern = ] 'user' 
当前数据库中的用户名。user 的数据类型为 sysname,默认值为 NULL。 

[ @LoginName = ] 'login' 
SQL Server 登录的名称。login 的数据类型为 sysname,默认值为 NULL。 
[ @Password = ] 'password' 
通过指定 Auto_Fix 创建的新 SQL Server 登录名分配的密码。如果已存在匹配的登录名,则映射该用户名与登录名且忽略 password。如果不存在匹配的登录名,则 sp_change_users_login 创建新的 SQL Server 登录名并分配 password 作为新登录名的密码。password 的数据类型为 sysname,且不能为 NULL。 




SQL Server 2005/2008的解决办法

(SQL2005中,由于微软做了重大调整,正常情况下不允许对系统表进行即席更新操作,所以要采用和SQL 2000完全不同的操作手法)

孤立帐户,就是某个数据库的帐户只有用户名而没有登录名,这样的用户在用户库的sysusers系统表中存在,而在master数据库的syslogins中却没有对应的记录。

孤立帐户的产生一般是一下两种:
1.将备份的数据库在其它机器上还原;
2.重装系统或SQL SERVER之后只还原了用户库
解决方法是使用sp_change_users_login来修复。
sp_change_users_login的用法有三种
用法1:
exec sp_change_users_login 'REPORT'
列出当前数据库的孤立用户
用法2:
exec sp_change_users_login 'AUTO_FIX','用户名'  (SQL Express)

或者

exec sp_change_users_login 'AUTO_FIX','用户名',null,'新用户密码'  (SQL Server)
可以自动将用户名所对应的同名登录添加到syslogins中
用法3:
exec sp_change_users_login 'UPDATE_ONE','用户名','登录名'
将用户名映射为指定的登录名。

 

 

SQL Server2000-数据库迁移及孤立用户的解决办法

        有时候,我们会需要将一个数据库从一个服务器移到另一个服务器上。这种迁移分两种情况,一种是整个数据服务器全部迁移,一种是只移其中的个别数据库。
        相对来说,全部迁移比较好办,问题比较少,不过一般要考虑数据库停用造成的服务停顿问题。具体来说,全部迁移我一般采用以下两种简便方法:一、在目标机上做好服务后,目标机和源机都停止服务,直接将所有数据库文件拷到目标机上,此法要求两机数据库文件的目录一致。二、备份源机上所有数据库,包括系统表,然后在目标机上用这些备份文件一个一个数据库还原,注意系统数据库要求用单用户模式才能还原(停数据库,从命令提示符输入:sqlservr.exe -c -m)。此外,如果源与目标数据库的路径不一致时,要设置好还原到什么路径,否则还原也不能成功。
        全部还原一般不会出现与用户有关的问题,而迁个别数据库则容易产生用户问题,产生这些问题的原因是保存在数据库的sysusers表中的用户的ID和保存在master.dbo.syslogins的登录ID有出入,造成用户和数据库登录不能联系起来,引起存储过程不能用,权限不能归还用户等等问题,而且这种孤立在数据库中的用户是不能在企业管理器中删除、修改的。
        其实在M$的帮助中,这种用户账号叫做“孤立用户”,同时它也提供了解决的方案--把那个用户删除。
         可是删除这些用户并不是好方法,因为你以前做的跟这个用户有关的操作又要重新做,所以最好的办法是为这些用户找回与登录的关联。

前提是先建立好了对应的登录。

例子:比如还原时,发现了一个孤立用户abc。
于是,在目标数据库中,先建立名为abc的用户登录,然后以sa身份登录查询分析器,切换到目标数据库,比如ume(use ume;),执行下述语句段(替换具体的数据库名字),即可将孤立用户abc还原成目标库中的新用户abc

exec sp_configure 'allow updates',1 reconfigure with override
update db set sid=s.sid
from 具体的数据库名字.dbo.sysusers db 
join master.dbo.syslogins s on db.name=s.name
where db.sid != s.sid and db.islogin=1 
exec sp_configure 'allow updates',0 reconfigure with override