如何在跨服务器备份/恢复后维护SQL Server 2008数据库的登录功能?
我需要经常使用备份/恢复过程在服务器之间传输数据库。我遇到了一个问题,在恢复时没有维护登录信息,我希望防止这种情况发生 详情如下:如何在跨服务器备份/恢复后维护SQL Server 2008数据库的登录功能?,sql,database,sql-server-2008,database-backups,database-administration,Sql,Database,Sql Server 2008,Database Backups,Database Administration,我需要经常使用备份/恢复过程在服务器之间传输数据库。我遇到了一个问题,在恢复时没有维护登录信息,我希望防止这种情况发生 详情如下: 共有3台服务器,每台服务器运行一个SQL Server 2008 Express实例 我在这3台服务器之间传输数据库内容 我通过使用源数据库上的“备份”选项和目标数据库上的“还原”选项来传输数据库内容 恢复时,我使用选项覆盖现有数据库(替换) 每个服务器上的数据库名称都可以相同(尽管当前其中一个服务器上的名称略有不同。它们分别命名为xxx.mydatabase和l
- 共有3台服务器,每台服务器运行一个SQL Server 2008 Express实例
- 我在这3台服务器之间传输数据库内容
- 我通过使用源数据库上的“备份”选项和目标数据库上的“还原”选项来传输数据库内容
- 恢复时,我使用选项覆盖现有数据库(替换)
- 每个服务器上的数据库名称都可以相同(尽管当前其中一个服务器上的名称略有不同。它们分别命名为xxx.mydatabase和local.mydatabase)
- SQL Express的每个实例都有一个安全登录名“MyDatabaseUser”
- 每个数据库都有一个名为“MyDatabaseUser”的用户
或者,您需要将登录重新映射到用户
EXEC sp_change_users_login 'Auto_Fix', 'user'
其中语法如下:
EXEC sp_change_users_login 'UserName', 'LoginName'
我是这样做的:
public override void RemapDbUserLogins(string DbName)
{
string strSQL = @"
USE " + EscapeDbName(DbName) + @";
DECLARE @__DatabasePrincipal sysname --nvarchar(128)
DECLARE @__ServerPrincipal sysname --nvarchar(128)
DECLARE @__CurPrincipals CURSOR
SET @__CurPrincipals = CURSOR FOR
(
-- sysname: nvarchar(128)
-- Get Login for user
SELECT
dp.name AS user_name
--,sp.name AS login_name
,
CASE
WHEN sp.name IS NULL
THEN
CASE
WHEN 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = dp.name COLLATE Latin1_General_CI_AS)
THEN dp.name
WHEN dp.name LIKE '%[_]DE' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 3) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 3)
WHEN dp.name LIKE '%DE' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 2) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 2)
WHEN dp.name LIKE '%[_]EN' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 3) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 3)
WHEN dp.name LIKE '%EN' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 2) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 2)
WHEN dp.name LIKE '%[_]FR' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 3) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 3)
WHEN dp.name LIKE '%FR' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 2) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 2)
WHEN dp.name LIKE '%[_]IT' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 3) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 3)
WHEN dp.name LIKE '%IT' AND 1 = (SELECT COUNT(*) FROM sys.server_principals AS spSubSel WHERE spSubSel.name = SUBSTRING(dp.name, 1, LEN(dp.name) - 2) COLLATE Latin1_General_CI_AS)
THEN SUBSTRING(dp.name, 1, LEN(dp.name) - 2)
--ELSE 'foo' + SUBSTRING(dp.name, 1, LEN(dp.name) - 3)
--ELSE N'ApertureWebServices'
ELSE NULL --COLLATE Latin1_General_CI_AS
END
ELSE sp.name COLLATE Latin1_General_CI_AS
END AS CorrespondingUser
FROM sys.database_principals AS dp
LEFT JOIN sys.server_principals AS sp
ON sp.sid = dp.sid
WHERE dp.type_desc = 'SQL_USER'
AND dp.sid IS NOT NULL
AND dp.sid != 0
AND sp.name IS NULL -- WHERE sids don't match
)
OPEN @__CurPrincipals
FETCH NEXT FROM @__CurPrincipals INTO @__DatabasePrincipal, @__ServerPrincipal
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @__DatabasePrincipal + N' = ' + @__ServerPrincipal
--EXEC sp_helptext 'sp_change_users_login'
DECLARE @Action varchar(10) -- REPORT / UPDATE_ONE / AUTO_FIX
DECLARE @UserNamePattern sysname = NULL
DECLARE @LoginName sysname = NULL
DECLARE @Password sysname = NULL
SET @Action = 'Update_One'
SET @UserNamePattern = @__DatabasePrincipal -- N'ApertureWebServicesDE'
SET @LoginName = @__ServerPrincipal -- N'ApertureWebServices'
IF @LoginName IS NOT NULL
BEGIN
PRINT 'EXECUTE sp_change_users_login @Action = ''' + @Action + N''', @UserNamePattern = ''' + @UserNamePattern + N''', @LoginName = ''' + @LoginName + N''', @Password = ' + ISNULL(N'''' + @Password + N'''', N'NULL')
EXECUTE sp_change_users_login @Action, @UserNamePattern, @LoginName, @Password
END
ELSE
BEGIN
PRINT N'Ignored user ' + @UserNamePattern
END
FETCH NEXT FROM @__CurPrincipals INTO @__DatabasePrincipal, @__ServerPrincipal
END
CLOSE @__CurPrincipals
DEALLOCATE @__CurPrincipals
";
ExecuteWithoutTransaction(strSQL);
} // End Sub RemapDbUserLogins
很好的答案和一些好的SQL。我做了测试,这些都很好。我很感激。我对您回答的第一行“将所有SQL用户放入sysadmin角色”有一个问题。这是否意味着我可以通过将断开连接的用户设置为系统管理员角色来防止连接断开?@RacerNerd:是的,这正是它的意思,但也意味着该用户将拥有系统管理员权限。