고아 사용자 찾기


12

SQL Server 2005에는 서버 수준에 존재하지 않는 사용자 (서버 수준에서 삭제되었지만 데이터베이스가 삭제되기 전에 데이터베이스에서 연결 해제되지 않은 계정) 또는 연결되지 않은 계정을 찾는 방법이 있습니까? (계정은 서버 수준에서 삭제되었지만 DB 수준에서는 삭제되지 않았지만 다시 읽었지만 db 수준은 정리되지 않았습니다.)

나는 매우 지저분한 서버를 가지고 있으며 이것을 찾기 위해 쿼리를 실행하면 멋질 것입니다.


답변:


15

Brent Ozar Unlimited 사이트다음 스크립트는 모든 데이터베이스를 반복하고 고아 사용자를 drop 명령과 함께 데이터베이스별로 나열하여 제거합니다. 이것을 처리하는 더 깔끔하고 새로운 방법이있을 수 있지만 2005-2012에서 올바르게 작동하는 것으로 보입니다.

DECLARE @SQL nvarchar(2000)
DECLARE @name nvarchar(128)
DECLARE @database_id int

SET NOCOUNT ON;

IF NOT EXISTS 
    (SELECT name FROM tempdb.sys.tables WHERE name like '%#orphan_users%')
BEGIN
    CREATE TABLE #orphan_users
        (
        database_name nvarchar(128) NOT NULL,
        [user_name] nvarchar(128) NOT NULL,
        drop_command_text nvarchar(200) NOT NULL
        )
END

CREATE TABLE #databases 
(
    database_id int NOT NULL
    , database_name nvarchar(128) NOT NULL
    , processed bit NOT NULL
)

INSERT
    #databases 
    ( database_id
    , database_name
    , processed )
SELECT 
    database_id
    , name
    , 0 
FROM 
    master.sys.databases 
WHERE 
    name NOT IN 
    ('master'
    , 'tempdb'
    , 'msdb'
    , 'distribution'
    , 'model')

WHILE (SELECT COUNT(processed) FROM #databases WHERE processed = 0) > 0
BEGIN
    SELECT TOP 1
        @name = database_name,
        @database_id = database_id
    FROM #databases
    WHERE processed = 0
    ORDER BY database_id

    SELECT @SQL =

'USE [' + @name + '];
INSERT INTO #orphan_users (database_name, user_name, drop_command_text)
SELECT 
    DB_NAME()
    , u.name
    , ' + '''' 
    + 'USE [' + @name + ']; ' 
    + 'DROP USER [' 
    + '''' + ' + u.name 
    + ' + '''' + '] ' 
    + '''' + '
FROM
    master..syslogins l
RIGHT JOIN 
    sysusers u 
ON l.sid = u.sid
WHERE   
    l.sid IS NULL
AND issqlrole <> 1
AND isapprole <> 1
AND ( u.name <> ' + '''' + 'INFORMATION_SCHEMA' + ''''
        + ' AND u.name <> ' + '''' + 'guest' + ''''
        + ' AND u.name <> ' + '''' + 'dbo' + ''''
        + ' AND u.name <> ' + '''' + 'sys' + ''''
        + ' AND u.name <> ' + '''' + 'system_function_schema' + '''' + ')'

    PRINT @SQL;

    EXEC sys.sp_executesql @SQL

    UPDATE 
        #databases 
    SET 
        processed = 1 
    WHERE 
        database_id = @database_id;
END

SELECT 
    database_name
    , [user_name]
    , drop_command_text 
FROM 
    #orphan_users 
ORDER BY 
    [database_name]
    , [user_name];

DROP TABLE #databases;
DROP TABLE #orphan_users;

SET NOCOUNT OFF;

4

스크립트를 게시 해 주셔서 감사합니다. 처음부터 작성하는 데 많은 시간을 절약했습니다. "데이터베이스 보안 주체가 데이터베이스에서 스키마를 소유하고 삭제할 수 없습니다"라는 오류가 발생하는 문제가 발생하여 조금 수정했습니다. 스크립트를 수정하여 SCHEMA 오류 및 역할 오류에 대한 명령을 생성해야합니다.

이것이 누군가를 도울 수 있기를 바랍니다 ..

DECLARE @SQL nvarchar(2000)
DECLARE @name nvarchar(128)
DECLARE @database_id int

SET NOCOUNT ON;

IF NOT EXISTS 
    (SELECT name FROM tempdb.sys.tables WHERE name like '%#orphan_users%')
BEGIN
    CREATE TABLE #orphan_users
        (
        database_name nvarchar(128) NOT NULL,
        [user_name] nvarchar(128) NOT NULL,
        drop_command_text nvarchar(200) NOT NULL,
        drop_schema_text nvarchar(200) not null,
        drop_role_text nvarchar(200) not null
        )
END

CREATE TABLE #databases 
(
    database_id int NOT NULL
    , database_name nvarchar(128) NOT NULL
    , processed bit NOT NULL
)

INSERT
    #databases 
    ( database_id
    , database_name
    , processed )
SELECT 
    database_id
    , name
    , 0 
FROM 
    master.sys.databases 
WHERE 
    name NOT IN 
    ('master'
    , 'tempdb'
    , 'msdb'
    , 'distribution'
    , 'model')

WHILE (SELECT COUNT(processed) FROM #databases WHERE processed = 0) > 0
BEGIN
    SELECT TOP 1
        @name = database_name,
        @database_id = database_id
    FROM #databases
    WHERE processed = 0
    ORDER BY database_id

    SELECT @SQL =

'USE [' + @name + '];
INSERT INTO #orphan_users (database_name, user_name, drop_command_text, Drop_schema_text, drop_role_text)
SELECT 
    DB_NAME()
    , u.name
    , 
        ' + '''' 
        + 'USE [' + @name + ']; ' 
        + 'DROP USER [' 
        + '''' + ' + u.name 
        + ' + '''' + '] ' 
        + '''' + '
    , 
        ' + '''' + 'USE [' + @name + ']; ' +
        'ALTER AUTHORIZATION ON SCHEMA::[' 
        + '''' + ' + u.name 
        + ' + '''' + ']  TO [dbo]' + '''' + '
    , 
        ' + '''' + 'USE [' + @name + ']; ' +
        'ALTER AUTHORIZATION ON Role::[' 
        + '''' + ' + u.name 
        + ' + '''' + ']  TO [dbo]' + '''' + '
FROM
    master..syslogins l
RIGHT JOIN 
    sysusers u 
ON l.sid = u.sid
WHERE   
    l.sid IS NULL
AND issqlrole <> 1
AND isapprole <> 1
AND ( u.name <> ' + '''' + 'INFORMATION_SCHEMA' + ''''
        + ' AND u.name <> ' + '''' + 'guest' + ''''
        + ' AND u.name <> ' + '''' + 'dbo' + ''''
        + ' AND u.name <> ' + '''' + 'sys' + ''''
        + ' AND u.name <> ' + '''' + 'system_function_schema' + '''' + ')'

    PRINT @SQL;

    EXEC sys.sp_executesql @SQL

    UPDATE 
        #databases 
    SET 
        processed = 1 
    WHERE 
        database_id = @database_id;
END

SELECT 
    database_name
    , [user_name]
    , drop_command_text 
    , Drop_schema_text
    , drop_role_text
FROM 
    #orphan_users 
ORDER BY 
    [database_name]
    , [user_name];

DROP TABLE #databases;
DROP TABLE #orphan_users;

SET NOCOUNT OFF;

3

이 sp_change_users_login은 SQL 2008부터 감가 상각되지만 여전히 잘 작동합니다. 'report'옵션을 전달하면 연관된 로그인이없는 모든 사용자가 나열됩니다.

EXEC sp_change_users_login 'report'

모든 데이터베이스에 대해 실행하려면 다음과 같이하십시오.

EXEC sp_msforeachdb 'use [?]; PRINT ''?''; EXEC sp_change_users_login ''report'';'

BOL에서 찾아 보면 "분리 된"사용자를 수정하는 옵션도 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.