/*
Script to discover orphaned database users linked to a/an SQL Server login. This is necessary for access control to a database following context and permission
*/

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 INTO #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;
