用于查找数据库用户是否拥有架构的通用查询

时间:2011-02-07 12:31:07

标签: sql sql-server

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

  

Msg 15138,Level 16,State 1,Line 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

2 个答案:

答案 0 :(得分:9)

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

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 :(得分:0)

通常来说,这些模式与其拥有的用户一样不受欢迎。因此,在删除用户之前先删除它们是明智的。如果他们没有对象,这实际上很简单。

此脚本删除孤立的用户,首先删除他们拥有的任何空模式。 @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;