通用查询来查找数据库用户是否拥有模式

问题描述 投票:0回答:2

我们的数据库中有很多 DBUser。我们必须从数据库中清除所有这些用户。当我尝试从数据库中删除用户时,由于以下错误而失败

消息 15138,第 16 级,状态 1,第 2 行 数据库主体拥有一个模式 在数据库中,并且不能 掉下来了。

所以我找到了解决方案,即将架构的所有权更改为

dbo
。现在我可以使用下面的脚本删除用户

SELECT name FROM  sys.schemas WHERE principal_id = USER_ID('myUser')
ALTER AUTHORIZATION ON SCHEMA::SchemaName TO dbo 
GO
DROP USER myUser

但是我想删除一些用户,所以我需要生成通用脚本。 我正在使用 SQL Server 2008

sql sql-server sql-server-2008
2个回答
12
投票

这将为您提供针对拥有它们的用户的完整架构列表:

SELECT db.name AS [DB User], s.name AS [Schema]
FROM sys.database_principals db
JOIN sys.schemas s ON s.principal_id = db.principal_id

1
投票

一般来说,这些模式与其所属用户一样不受欢迎。 因此,明智的做法是在删除用户之前删除它们。 如果他们没有对象的话,这真的很简单。

此脚本会删除孤立用户,首先删除他们拥有的任何空架构。 @Debug = 1 表示仅打印命令。 将 @Debug 设置为 0 将导致命令被执行。

SET NOCOUNT ON;

DECLARE @debug BIT;
SELECT @debug = 1;

DECLARE @commands TABLE
(
    id INT IDENTITY(1, 1) NOT NULL,
    command sysname NOT NULL
);

INSERT @commands
(
    command
)
SELECT CASE
           WHEN NOT EXISTS
                    (
                        SELECT 1 FROM sys.objects so WHERE so.schema_id = sch.schema_id
                    ) THEN
               N'DROP SCHEMA [' + sch.name + N'];'
           ELSE
               N'PRINT (''Schema ' + sch.name + ' has objects and cannot be dropped'')'
       END
FROM sys.schemas sch
WHERE EXISTS
(
    SELECT 1
    FROM sys.database_principals dp
    WHERE sch.principal_id = dp.principal_id
          AND NOT EXISTS
    (
        SELECT 1 FROM sys.server_principals sp WHERE sp.sid = dp.sid
    )
          AND type NOT IN ( 'R' )
          AND
          (
              sid IS NOT NULL
              AND sid <> 0
          )
);

INSERT @commands
(
    command
)
SELECT N'DROP USER [' + name + N'];'
FROM sys.database_principals dp
WHERE NOT EXISTS
(
    SELECT 1 FROM sys.server_principals sp WHERE sp.sid = dp.sid
)
      AND type NOT IN ( 'R' )
      AND
      (
          sid IS NOT NULL
          AND sid <> 0
      );

DECLARE @command sysname;
DECLARE @loop INT,
        @loopmax INT;
SELECT @loop = 1,
       @loopmax = MAX(id)
FROM @commands;

WHILE @loop <= @loopmax
BEGIN
    SELECT @command = command
    FROM @commands
    WHERE id = @loop;

    IF @debug = 0
        EXECUTE (@command);
    ELSE
        PRINT (@command);

    SELECT @loop = @loop + 1;
END;
© www.soinside.com 2019 - 2024. All rights reserved.