Tìm người dùng mồ côi


12

Trong SQL Server 2005, có một cách để tìm người dùng không tồn tại ở cấp máy chủ (tài khoản đã bị xóa ở cấp máy chủ nhưng không được tách khỏi cơ sở dữ liệu trước khi bị xóa) hoặc tài khoản không được liên kết (một tài khoản có thể đã bị xóa ở cấp máy chủ nhưng không phải ở cấp độ db, sau đó được gắn lại nhưng mức db không bao giờ được xóa sạch).

Tôi đã có một máy chủ rất lộn xộn và thật tuyệt vời nếu có một truy vấn để chạy để tìm những máy chủ này.


Câu trả lời:


15

Tập lệnh sau từ trang Brent Ozar Unlimited lặp lại qua tất cả các cơ sở dữ liệu và liệt kê những người dùng mồ côi theo cơ sở dữ liệu, cùng với lệnh thả để loại bỏ chúng. Có thể có một cách xử lý gọn gàng hơn / mới hơn nhưng điều này dường như hoạt động chính xác vào năm 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

Tôi muốn đầu tiên THANK Mark cho đăng kịch bản. Nó tiết kiệm cho tôi rất nhiều thời gian để viết nó từ đầu. Tôi đã sửa đổi nó một chút kể từ khi tôi gặp phải vấn đề trong đó tôi nhận được lỗi thông báo lỗi "hiệu trưởng cơ sở dữ liệu sở hữu một lược đồ trong cơ sở dữ liệu và không thể bỏ được". Tôi đã sửa đổi tập lệnh để tạo các lệnh cho lỗi SCHema và cả lỗi Vai trò nếu bạn cũng nên lấy tập lệnh đó.

Hy vọng điều này sẽ giúp ai đó ngoài kia ..

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_usftimelogin này không được dùng nữa kể từ SQL 2008 nhưng vẫn hoạt động tốt. Nếu bạn chuyển qua tùy chọn 'báo cáo' thì nó sẽ liệt kê tất cả người dùng không có thông tin đăng nhập liên quan.

EXEC sp_change_users_login 'report'

Nếu bạn muốn chạy nó cho tất cả các cơ sở dữ liệu của bạn, bạn có thể làm điều đó như thế này.

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

Nếu bạn tra cứu nó trong BOL, bạn cũng sẽ tìm thấy các tùy chọn để sửa lỗi người dùng "mồ côi".

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.