SQL Server 2005では、サーバーレベルで存在しないユーザー(サーバーレベルで削除されたが、削除される前にデータベースとの関連付けが解除されなかったアカウント)またはリンクされていないアカウントを見つける方法はありますか(アカウントはサーバーレベルでは削除されているが、dbレベルでは削除されていない可能性があります。その後、追加されましたが、dbレベルはクリーンアップされませんでした)。
私は非常に厄介なサーバーを持っているので、これらを見つけるために実行するクエリがあれば素晴らしいでしょう。
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;
最初に台本を投稿してくれてありがとうマークになりたかった。それは私にそれをゼロから書く時間の多くを節約しました。 「データベースプリンシパルはデータベース内のスキーマを所有しているため、削除できません」というエラーが表示されるという問題に遭遇したので、少し修正しました。スクリプトを変更して、スキーマエラーのコマンドと、ロールエラーも取得する必要がある場合はロールエラーのコマンドを生成しました。
これが誰かを助けることを願っています。
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;
このsp_change_users_loginは、SQL 2008で廃止されましたが、引き続き正常に機能します。 「レポート」オプションを渡すと、関連付けられたログインを持たないすべてのユーザーがリストされます。
EXEC sp_change_users_login 'report'
すべてのデータベースに対して実行したい場合は、次のように実行できます。
EXEC sp_msforeachdb 'use [?]; PRINT ''?''; EXEC sp_change_users_login ''report'';'
BOLで検索すると、「孤立した」ユーザーを修正するためのオプションも見つかります。