生成脚本以删除或映射 SQL Server 实例中的孤立用户

0 sql-server powershell

我对 SQL Server 很陌生。我有一个脚本,它在所有数据库中查找孤立用户并生成脚本以删除或映射用户以正确登录(如果可用)。

由于我想在大量服务器上运行该脚本,所以我想到了使用 PowerShell 来帮助我。但我现在有两个问题:

  1. 脚本错误
  2. Power-shell 执行出错

问题 1:以下脚本本身返回输出,但仍显示一些错误。我试图调试,但我无法这样做。

DECLARE @orphan_users TABLE (
    Server NVARCHAR(MAX),
    DBName sysname,
    [user_name] sysname,
    type_desc nvarchar(60),
    default_schema_name sysname NULL,
    create_date datetime,
    modify_date DATETIME,
    [sid] VARBINARY(85),
    cr_type int
); 

INSERT INTO @orphan_users (Server,
    DBname,
    [user_name],
    type_desc,
    default_schema_name,
    create_date,
    modify_date,
    [sid],
    cr_type
) 
EXEC sp_msforeachdb 
'use [?] 
SELECT 
    @@SERVERNAME 
    ,DB_NAME() DBname 
    ,name 
    ,type_desc 
    ,default_schema_name 
    ,create_date 
    ,modify_date 
    ,[sid] 
    ,Datalength(sid) AA 
from sys.database_principals 
where type in (''S'') 
and [sid] not in ( select [sid] from sys.server_principals where type in (''G'',''S'',''U'') ) 
and name not in (''dbo'',''guest'',''INFORMATION_SCHEMA'',''sys'' ,''MS_DataCollectorInternalUser'')'; 

DECLARE @db_users TABLE (
    [LogInAtServerLevel] NVARCHAR(MAX),
    [UserAtDBLevel] NVARCHAR(MAX), 
    DBname sysname
); 

INSERT INTO @db_users ([LogInAtServerLevel], [UserAtDBLevel],DBname) 
EXEC sp_msforeachdb 
'use [?] 
SELECT 
    susers.[name],
    users.[name],
    DB_NAME() DBname?????????????  
from sys.database_principals users 
inner join sys.database_role_members link 
?? on link.member_principal_id = users.principal_id 
inner join sys.database_principals roles 
?? on roles.principal_id = link.role_principal_id 
inner join sys.server_principals susers 
?? on susers.sid = users.sid'; 

SELECT 
    a.Server,
    a.DBName,
    a.user_name,
    b.name,cr_type,
    c.UserAtDBLevel, 
    CASE 
        WHEN (b.name IS NULL) and (cr_type > 17) 
            THEN 'USE ' + QUOTENAME(a.DBname) + '; DROP USER ' + QUOTENAME(a.user_name) + ';' 
        WHEN (b.name IS not NULL) and (cr_type < 17) and (c.UserAtDBLevel is null) 
            THEN 'USE ' + QUOTENAME(a.DBname) + '; ALTER USER ' + QUOTENAME(a.user_name) + ' WITH LOGIN = ' + QUOTENAME(b.name)+';' 
        WHEN (b.name IS not NULL) and (cr_type < 17) and (c.UserAtDBLevel is not null) 
            THEN 'USE ' + QUOTENAME(a.DBname) + '; DROP USER ' + QUOTENAME(a.user_name) + ';' 
        WHEN (b.name IS NULL) 
            THEN 'USE ' + QUOTENAME(a.DBname) + '; DROP USER ' + QUOTENAME(a.user_name) + ';' 
        WHEN (b.name IS not NULL) and (cr_type > 17) 
            THEN 'USE ' + QUOTENAME(a.DBname) + '; DROP USER ' + QUOTENAME(a.user_name) + ';' 
    END as [remediation] 
FROM ((@orphan_users a 
    left join sys.server_principals b on a.user_name = b.name)  
    left join @db_users c on c.DBname=a.DBName and c.LogInAtServerLevel=b.name) 
ORDER BY a.user_name; 
Run Code Online (Sandbox Code Playgroud)

结果是

在此处输入图片说明

但是出现错误后,实例中的所有数据库都会出现类似的错误

'tempdbfrom' 附近的语法不正确。消息 102,级别 15,状态 1,第 3 行
'modelfrom' 附近的语法不正确。消息 102,级别 15,状态 1,第 3 行
“msdbfrom”附近的语法不正确。消息 102,级别 15,状态 1,第 3 行
'dbamonfrom' 附近的语法不正确。消息 102,级别 15,状态 1,第 3 行

问题 2:由于脚本是准确的(至少在我的环境中),所以我尝试使用 power-shell 运行它,如下所示。它只返回错误,没有输出

Invoke-SqlCmd `
    -InputFile "D:\temp\up.sql" `
    -ServerInstance 'abc\sql2012' `
    -IncludeSqlUserErrors
Run Code Online (Sandbox Code Playgroud)

我已经尝试了从使用 > 重定向输出开始和停止转录的所有方法。他们似乎都没有捕获查询给出的结果,但是错误被准确捕获。

如果任何一个问题得到解决,对我来说都会有很大的帮助。

alr*_*roc 6

dbatools模块已经为您解决了这个问题。

  • Get-DbaDbOrphanUser - 报告一个或多个数据库中没有相应登录名的所有用户
  • Repair-DbaDbOrphanUser - 查找孤儿用户,如果有同名登录,它将重新映射它们。
  • Remove-DbaDbOrphanUser- 定位孤立用户并将其从数据库中删除(您也可以这样做Repair-DbaDbOrphanUser -RemoveNotExisting)。