diff --git a/LICENSE b/LICENSE index 44760dc..15bc72f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Anthony Duguid +Copyright (c) 2019 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/PMDB.Remove database locks.sql b/PMDB.Remove database locks.sql index 29d3b44..043ed10 100644 --- a/PMDB.Remove database locks.sql +++ b/PMDB.Remove database locks.sql @@ -19,8 +19,11 @@ PRINT 'show the blocked processes. ' PRINT '=====================================================================' GO -SELECT DB_NAME(dbid) as 'Database Name', * FROM master.dbo.sysprocesses WITH (NOLOCK) -WHERE BLOCKED <> 0 +SELECT + [Database Name] = DB_NAME([dbid]) + , * +FROM [master].[dbo].[sysprocesses] WITH(NOLOCK) +WHERE [BLOCKED] != 0; --DB_NAME(dbid) = 'PMDB_TEST' -- change the database name here PRINT '=====================================================================' @@ -28,7 +31,10 @@ PRINT 'show the blocked process record. ' PRINT '=====================================================================' GO -SELECT DB_NAME(dbid) AS 'Database Name', * FROM master.dbo.sysprocesses +SELECT + [Database Name] = DB_NAME([dbid]) + , * +FROM [master].[dbo].[sysprocesses]; WHERE SPID = 212 -- update the spid here PRINT '=====================================================================' @@ -36,14 +42,14 @@ PRINT 'get the sql statement of the blocked process for the ticket. ' PRINT '=====================================================================' GO -DBCC INPUTBUFFER (212) -- update the spid here +DBCC INPUTBUFFER(212); -- update the spid here PRINT '=====================================================================' PRINT 'remove the blocked process. ' PRINT '=====================================================================' GO ---KILL 212 +--KILL 212; PRINT '=====================================================================' PRINT 'Finished!' diff --git a/README.md b/README.md index 78b9d10..374effe 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,9 @@ # SQL Server Scripts Various scripts I use for SQL Server +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE "MIT License Copyright © Anthony Duguid") +![current_build SQL_SERVER_2016](https://img.shields.io/badge/current_build-SQL_SERVER_2016-red.svg) + ## General Database Scripts * [Check Index Fragmentation](SSDB.Check_Index_Fragmentation.sql) * [Database Backup](SSDB.Restore_Database_Backup.sql) diff --git a/SSDB.Check_Index_Fragmentation.sql b/SSDB.Check_Index_Fragmentation.sql index f6f3f86..b0e5f72 100644 --- a/SSDB.Check_Index_Fragmentation.sql +++ b/SSDB.Check_Index_Fragmentation.sql @@ -1,29 +1,28 @@ /*--------------------------------------------------------------------------------------+ | Purpose: How to Check Index Fragmentation on Indexes in a Database -| Note: SQLCmdMode Script +---------------------------------------------------------------------------------------*/ SELECT - 'Schema' = dbschemas.[name] - , 'Table' = dbtables.[name] - , 'Index' = dbindexes.[name] - , indexstats.avg_fragmentation_in_percent - , indexstats.page_count - , SqlScript = + [Schema] = dbschemas.[name] + , [Table] = dbtables.[name] + , [Index] = dbindexes.[name] + , indexstats.[avg_fragmentation_in_percent] + , indexstats.[page_count] + , [SqlScript] = CASE - WHEN indexstats.avg_fragmentation_in_percent > 30 THEN 'ALTER INDEX [' + dbindexes.[name] + '] ON [' + dbschemas.[name] + '].[' + dbtables.[name] + '] REBUILD WITH (ONLINE = ON)' - WHEN indexstats.avg_fragmentation_in_percent > 5 AND indexstats.avg_fragmentation_in_percent < 30 THEN 'ALTER INDEX [' + dbindexes.[name] + '] ON [' + dbschemas.[name] + '].[' + dbtables.[name] + '] REORGANIZE' + WHEN indexstats.[avg_fragmentation_in_percent] > 30 THEN 'ALTER INDEX [' + dbindexes.[name] + '] ON [' + dbschemas.[name] + '].[' + dbtables.[name] + '] REBUILD WITH (ONLINE = ON)' + WHEN indexstats.[avg_fragmentation_in_percent] > 5 AND indexstats.[avg_fragmentation_in_percent] < 30 THEN 'ALTER INDEX [' + dbindexes.[name] + '] ON [' + dbschemas.[name] + '].[' + dbtables.[name] + '] REORGANIZE' ELSE NULL END FROM - sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats - INNER JOIN sys.tables dbtables on dbtables.[object_id] = indexstats.[object_id] - INNER JOIN sys.schemas dbschemas on dbtables.[schema_id] = dbschemas.[schema_id] - INNER JOIN sys.indexes AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id] AND indexstats.index_id = dbindexes.index_id + [sys].[dm_db_index_physical_stats] (DB_ID(), NULL, NULL, NULL, NULL) AS indexstats + INNER JOIN [sys].[tables] AS dbtables ON dbtables.[object_id] = indexstats.[object_id] + INNER JOIN [sys].[schemas] AS dbschemas ON dbtables.[schema_id] = dbschemas.[schema_id] + INNER JOIN [sys].[indexes] AS dbindexes ON dbindexes.[object_id] = indexstats.[object_id] AND indexstats.index_id = dbindexes.index_id WHERE 1=1 - AND indexstats.database_id = DB_ID() + AND indexstats.[database_id] = DB_ID() AND dbindexes.[name] IS NOT NULL --AND dbindexes.[name] = 'IX_IndexName' ORDER BY - indexstats.avg_fragmentation_in_percent desc + indexstats.[avg_fragmentation_in_percent] DESC diff --git a/SSDB.RowLevelAuditAdd.sql b/SSDB.RowLevelAuditAdd.sql new file mode 100644 index 0000000..e5c7c09 --- /dev/null +++ b/SSDB.RowLevelAuditAdd.sql @@ -0,0 +1,252 @@ +CREATE PROCEDURE [dbo].[RowLevelAuditAdd] + @DatabaseName NVARCHAR(50) = NULL + , @SchemaName NVARCHAR(50) = NULL + , @TableName NVARCHAR(50) = NULL +AS +BEGIN + +/* +'-------------------------------------------------------------------------------------------------------------------- +' Purpose: Adds row level auditing columns to a table +' Example: EXEC dbo.RowLevelAuditAdd 'YourDatabase', 'dbo', 'ORGN'; +' Note: The table must have a primary key to create the update trigger +'-------------------------------------------------------------------------------------------------------------------- + + ----------------------------------------------------- + -->>>>>>>>>>>>>>>>> FOR DEBUGGING <<<<<<<<<<<<<<<<<<< + ----------------------------------------------------- + BEGIN + DECLARE @DatabaseName NVARCHAR(50) + DECLARE @SchemaName NVARCHAR(50) + DECLARE @TableName NVARCHAR(50) + SET @DatabaseName = 'YourDatabase' + SET @SchemaName = 'dbo' + SET @TableName = 'ORGN' + ----------------------------------------------------- + ----------------------------------------------------- + + --remove the table if exists + IF OBJECT_ID('dbo.ORGN', 'U') IS NOT NULL + DROP TABLE dbo.ORGN; + + --create the table + CREATE TABLE [dbo].[ORGN] ( + [ORGN_ID] INT IDENTITY (1, 1) NOT NULL, + [ORGN_ABBR] VARCHAR (5) NOT NULL, + [ORGN_NAME] VARCHAR (100) NULL + ); + + --Add the keys + ALTER TABLE [dbo].[ORGN] + ADD CONSTRAINT [PK_ORGN] PRIMARY KEY NONCLUSTERED ([ORGN_ID] ASC); + ALTER TABLE [dbo].[ORGN] + ADD CONSTRAINT [UK_ORGN] UNIQUE NONCLUSTERED ([ORGN_ABBR] ASC); + + --Add some test records + INSERT INTO dbo.ORGN (ORGN_ABBR, ORGN_NAME) VALUES('AABA', 'Altaba Inc'); + INSERT INTO dbo.ORGN (ORGN_ABBR, ORGN_NAME) VALUES('AAPL', 'Apple Inc'); + INSERT INTO dbo.ORGN (ORGN_ABBR, ORGN_NAME) VALUES('GOOG', 'Alphabet Inc'); + INSERT INTO dbo.ORGN (ORGN_ABBR, ORGN_NAME) VALUES('MSFT', 'Microsoft Corporation'); + INSERT INTO dbo.ORGN (ORGN_ABBR, ORGN_NAME) VALUES('TSLA', 'Tesla Inc'); + + --test procedure + EXEC dbo.RowLevelAuditAdd 'YourDatabase', 'dbo', 'ORGN'; + +*/ + + SET XACT_ABORT ON + BEGIN TRANSACTION; + SET NOCOUNT ON + + DECLARE @SqlCommand NVARCHAR(1000) + DECLARE @TableKey NVARCHAR(1000) + DECLARE @UserName NVARCHAR(50) + DECLARE @CreatedId NVARCHAR(50) + DECLARE @CreatedDate NVARCHAR(50) + DECLARE @ModifiedId NVARCHAR(50) + DECLARE @ModifiedDate NVARCHAR(50) + DECLARE @TodayDate NVARCHAR(50) + + SET @CreatedId = 'CreatedId' + SET @CreatedDate = 'CreatedDate' + SET @ModifiedId = 'ModifiedId' + SET @ModifiedDate = 'ModifiedDate' + SET @UserName = LOWER(LEFT(RIGHT(SYSTEM_USER,(LEN(SYSTEM_USER)-CHARINDEX('\',SYSTEM_USER))), 50)) + SET @TodayDate = FORMAT(GETDATE(), 'dd-MMM-yyyy HH:mm:ss', 'en-US' ) + + PRINT '====================================================================='; + PRINT 'START - ALTER [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + ']... '; + + IF COL_LENGTH(@DatabaseName + '.' + @SchemaName + '.' + @TableName, @CreatedId) IS NULL + BEGIN + + PRINT '====================================================================='; + PRINT 'START - ADD COLUMN [' + @CreatedId + ']... '; + + PRINT '1. alter table add ' + @CreatedId + ' column... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD [' + @CreatedId + '] [NVARCHAR](50) NULL' + EXEC (@SqlCommand) + + PRINT '2. update new column to a value... ' + @UserName; + SET @SqlCommand = 'UPDATE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] SET [' + @CreatedId + '] =''' + @UserName + ''' WHERE [' + @CreatedId + '] IS NULL' + EXEC (@SqlCommand) + + PRINT '3. alter table alter new column add constraints... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ALTER COLUMN [' + @CreatedId + '] [NVARCHAR](50) NOT NULL' + EXEC (@SqlCommand) + + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD CONSTRAINT [DF_' + @TableName + '_' + @CreatedId + '] DEFAULT (LOWER(LEFT(RIGHT(SYSTEM_USER,(LEN(SYSTEM_USER)-CHARINDEX(''\'',SYSTEM_USER))), 50))) FOR [' + @CreatedId + ']' + EXEC (@SqlCommand) + + PRINT '4. add column description... '; + EXEC [sys].sp_addextendedproperty @name=N'MS_Description', @value=N'Who created the record' , @level0type=N'SCHEMA',@level0name=@SchemaName, @level1type=N'TABLE',@level1name=@TableName, @level2type=N'COLUMN',@level2name=@CreatedId; + + PRINT 'END - ADD COLUMN [' + @CreatedId + ']... '; + PRINT '====================================================================='; + END + + IF COL_LENGTH(@DatabaseName + '.' + @SchemaName + '.' + @TableName, @CreatedDate) IS NULL + BEGIN + + PRINT '====================================================================='; + PRINT 'START - ADD COLUMN [' + @CreatedDate + ']... '; + + PRINT '1. alter table add ' + @CreatedDate + ' column... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD [' + @CreatedDate + '] [DATETIME] NULL' + EXEC (@SqlCommand) + + PRINT '2. update new column to a value... ' + @TodayDate; + SET @SqlCommand = 'UPDATE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] SET [' + @CreatedDate + '] = ''' + @TodayDate+ ''' WHERE [' + @CreatedDate + '] IS NULL' + EXEC (@SqlCommand) + + PRINT '3. alter table alter new column add constraints... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ALTER COLUMN [' + @CreatedDate + '] [DATETIME] NOT NULL' + EXEC (@SqlCommand) + + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD CONSTRAINT [DF_' + @TableName + '_' + @CreatedDate + '] DEFAULT (GETDATE()) FOR [' + @CreatedDate + ']' + EXEC (@SqlCommand) + + PRINT '4. add column description... '; + EXEC [sys].sp_addextendedproperty @name=N'MS_Description', @value=N'The date and time the record was created' , @level0type=N'SCHEMA',@level0name=@SchemaName, @level1type=N'TABLE',@level1name=@TableName, @level2type=N'COLUMN',@level2name=@CreatedDate; + + PRINT 'END - ADD COLUMN [' + @CreatedDate + ']... '; + PRINT '====================================================================='; + END + + IF COL_LENGTH(@DatabaseName + '.' + @SchemaName + '.' + @TableName, @ModifiedId) IS NULL + BEGIN + + PRINT '====================================================================='; + PRINT 'START - ADD COLUMN [' + @ModifiedId + ']... '; + + PRINT '1. alter table add ' + @ModifiedId + ' column... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD [' + @ModifiedId + '] [NVARCHAR](50) NULL' + EXEC (@SqlCommand) + + PRINT '2. update new column to a value... ' + @UserName; + SET @SqlCommand = 'UPDATE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] SET [' + @ModifiedId + '] =''' + @UserName + ''' WHERE [' + @ModifiedId + '] IS NULL' + EXEC (@SqlCommand) + + PRINT '3. alter table alter new column add constraints... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ALTER COLUMN [' + @ModifiedId + '] [NVARCHAR](50) NOT NULL' + EXEC (@SqlCommand) + + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD CONSTRAINT [DF_' + @TableName + '_' + @ModifiedId + '] DEFAULT (LOWER(LEFT(RIGHT(SYSTEM_USER,(LEN(SYSTEM_USER)-CHARINDEX(''\'',SYSTEM_USER))), 50))) FOR [' + @ModifiedId + ']' + EXEC (@SqlCommand) + + PRINT '4. add column description... '; + EXEC [sys].sp_addextendedproperty @name=N'MS_Description', @value=N'Who modified the record' , @level0type=N'SCHEMA',@level0name=@SchemaName, @level1type=N'TABLE',@level1name=@TableName, @level2type=N'COLUMN',@level2name=@ModifiedId; + + PRINT 'END - ADD COLUMN [' + @ModifiedId + ']... '; + PRINT '====================================================================='; + END + + IF COL_LENGTH(@DatabaseName + '.' + @SchemaName + '.' + @TableName, @ModifiedDate) IS NULL + BEGIN + + PRINT '====================================================================='; + PRINT 'START - ADD COLUMN [' + @ModifiedDate + ']... '; + + PRINT '1. alter table add ' + @ModifiedDate + ' column... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD [' + @ModifiedDate + '] [DATETIME] NULL' + EXEC (@SqlCommand) + + PRINT '2. update new column to a value... ' + @TodayDate; + SET @SqlCommand = 'UPDATE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] SET [' + @ModifiedDate + '] = ''' + @TodayDate+ ''' WHERE [' + @ModifiedDate + '] IS NULL' + EXEC (@SqlCommand) + + PRINT '3. alter table alter new column add constraints... '; + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ALTER COLUMN [' + @ModifiedDate + '] [DATETIME] NOT NULL' + EXEC (@SqlCommand) + + SET @SqlCommand = 'ALTER TABLE [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + '] ADD CONSTRAINT [DF_' + @TableName + '_' + @ModifiedDate + '] DEFAULT (GETDATE()) FOR [' + @ModifiedDate + ']' + EXEC (@SqlCommand) + + PRINT '4. add column description... '; + EXEC [sys].sp_addextendedproperty @name=N'MS_Description', @value=N'The date and time the record was modified' , @level0type=N'SCHEMA',@level0name=@SchemaName, @level1type=N'TABLE',@level1name=@TableName, @level2type=N'COLUMN',@level2name=@ModifiedDate; + + PRINT 'END - ADD COLUMN [' + @ModifiedDate + ']... '; + PRINT '====================================================================='; + END + + IF NOT EXISTS (SELECT * FROM [sys].[triggers] WHERE [object_id] = OBJECT_ID(N'[' + @SchemaName + '].[TR_' + @TableName + '_LAST_UPDATED]')) + BEGIN + + PRINT '====================================================================='; + PRINT 'START - ADD TRIGGER [TR_' + @TableName + '_LAST_UPDATED]... '; + + PRINT '1. get primary key from information schema'; + SET @SqlCommand = 'USE ' + @DatabaseName + '; ' + SET @SqlCommand += ' SELECT ' + SET @SqlCommand += ' @TableKey = COALESCE(@TableKey, '''') + CASE WHEN [ORDINAL_POSITION] = 1 THEN ''ON'' ELSE ''AND'' END + '' t.'' + [COLUMN_NAME] + '' = i.'' + [COLUMN_NAME] + '' ''' + SET @SqlCommand += ' FROM' + SET @SqlCommand += ' [INFORMATION_SCHEMA].[KEY_COLUMN_USAGE]' + SET @SqlCommand += ' WHERE' + SET @SqlCommand += ' OBJECTPROPERTY(OBJECT_ID([CONSTRAINT_SCHEMA] + ''.'' + QUOTENAME([CONSTRAINT_NAME])), ''IsPrimaryKey'') = 1 ' + SET @SqlCommand += ' AND [TABLE_NAME] = ''' + @TableName + '''' + SET @SqlCommand += ' AND [TABLE_SCHEMA] = ''' + @SchemaName + '''' + SET @SqlCommand += ' ORDER BY [ORDINAL_POSITION]' + EXEC sp_executeSQl @SqlCommand, N'@TableKey NVARCHAR(1000) OUTPUT', @TableKey OUTPUT + + PRINT '2. build trigger dynamically'; + SET @SqlCommand = 'USE ' + @DatabaseName + '; ' + SET @SqlCommand += ' CREATE TRIGGER [' + @SchemaName + '].[TR_' + @TableName + '_LAST_UPDATED]' + CHAR(13); + SET @SqlCommand += ' ON [' + @SchemaName + '].[' + @TableName + ']' + CHAR(13); + SET @SqlCommand += ' AFTER UPDATE' + CHAR(13); + SET @SqlCommand += ' AS' + CHAR(13); + SET @SqlCommand += ' BEGIN' + CHAR(13); + SET @SqlCommand += CHAR(9) + ' IF NOT UPDATE(' + @ModifiedDate + ')' + CHAR(13); + SET @SqlCommand += CHAR(9) + ' BEGIN' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + ' UPDATE t' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + ' SET' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + ' t.' + @ModifiedDate + ' = CURRENT_TIMESTAMP' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + ' , t.' + @ModifiedId + ' = LOWER(LEFT(RIGHT(SYSTEM_USER,(LEN(SYSTEM_USER)-CHARINDEX(''\'',SYSTEM_USER))), 50))' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + ' FROM [' + @SchemaName + '].[' + @TableName + '] AS t' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + ' INNER JOIN inserted AS i' + CHAR(13); + SET @SqlCommand += CHAR(9) + CHAR(9) + @TableKey + ';' + CHAR(13); + SET @SqlCommand += CHAR(9) + ' END' + CHAR(13); + SET @SqlCommand += ' END;' + CHAR(13); + EXEC (@SqlCommand) + + PRINT '3. enable trigger'; + SET @SqlCommand = 'USE ' + @DatabaseName + '; ' + SET @SqlCommand += ' ALTER TABLE [' + @SchemaName + '].[' + @TableName + '] ENABLE TRIGGER [TR_' + @TableName + '_LAST_UPDATED]'; + EXEC (@SqlCommand) + + PRINT 'END - ADD TRIGGER [' + @ModifiedDate + ']... '; + PRINT '====================================================================='; + END + + + PRINT 'END - ALTER [' + @DatabaseName + '].[' + @SchemaName + '].[' + @TableName + ']... '; + PRINT '====================================================================='; + + --PRINT '******* ROLLBACK TRANSACTION ******* '; + --ROLLBACK TRANSACTION; + + PRINT '******* COMMIT TRANSACTION ******* '; + COMMIT TRANSACTION; + +END + +GO diff --git a/SSDB.Row_Level_Auditing_Add.sql b/SSDB.Row_Level_Auditing_Add.sql index 18075ab..32ade74 100644 --- a/SSDB.Row_Level_Auditing_Add.sql +++ b/SSDB.Row_Level_Auditing_Add.sql @@ -160,7 +160,7 @@ BEGIN PRINT '====================================================================='; END - IF NOT EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[dbo].[TR_' + @TableName + '_LAST_UPDATED]')) + IF NOT EXISTS (SELECT * FROM sys.triggers WHERE object_id = OBJECT_ID(N'[' + @SchemaName + '].[TR_' + @TableName + '_LAST_UPDATED]')) BEGIN PRINT '====================================================================='; @@ -217,4 +217,4 @@ BEGIN END -GO \ No newline at end of file +GO diff --git a/SSDB.non-service_accounts.sql b/SSDB.non-service_accounts.sql new file mode 100644 index 0000000..3850b5a --- /dev/null +++ b/SSDB.non-service_accounts.sql @@ -0,0 +1,174 @@ +/*+--------------------------------------------------------------------------- +| Purpose: To check for non-service accounts +| Note: SQLCmdMode Script --> on the SSMS menu bar "Query" | "SQLCMD Mode" ++----------------------------------------------------------------------------- +*/ + +:setvar _server "YourServerName" -- change the server here +:setvar _database "master" +:connect $(_server) + +USE [$(_database)]; +GO + +:setvar login_name "" -- to search for an individual account enter it here e.g. "Domain\UserName" +:setvar ssrs_service_account "Domain\ssrs_service_account" + +SET XACT_ABORT ON +BEGIN TRANSACTION; + +PRINT '====================================================================='; +PRINT 'define all services accounts ... '; + +SELECT tbl.* INTO #service_accounts FROM (VALUES + ('##MS_PolicyEventProcessingLogin##') + , ('##MS_PolicyTsqlExecutionLogin##') + , ('NT AUTHORITY\SYSTEM') + , ('NT Service\MSSQLSERVER') + , ('NT SERVICE\SQLSERVERAGENT') + , ('NT SERVICE\SQLTELEMETRY') + , ('NT SERVICE\SQLWriter') + , ('NT SERVICE\Winmgmt') + , ('public') + , ('sa') +) tbl ([Login_Name]) + +PRINT '====================================================================='; +PRINT 'check databases owners ... '; + + SELECT + [Server_Name] = @@SERVERNAME + , [Database_Name] = db.[name] + , [Database_Owner] = sl.[Name] + , [CommandToRun] = (CASE WHEN db.[is_read_only] = 1 THEN '-- Remove ReadOnly State' WHEN db.[state_desc] = 'ONLINE' THEN 'ALTER AUTHORIZATION on DATABASE::[' + db.[name] + '] to [sa];' ELSE '-- Turn On ' END) + --, [Database_ID] = db.[database_id] + --, [Current_State] = db.[state_desc] + --, [Read_Only] = db.[is_read_only] + FROM + [master].[sys].[databases] AS db + INNER JOIN [master].[sys].[syslogins] AS sl ON db.[owner_sid] = sl.[sid] + WHERE + 1=1 + AND sl.[Name] NOT IN(SELECT [Login_Name] FROM #service_accounts) + AND (sl.[Name] = N'$(login_name)' OR N'$(login_name)' = N'') + ORDER BY + db.[Name] + +PRINT '====================================================================='; +PRINT 'check databases users ... '; + + DECLARE @dbs_users TABLE + ( + [Database_Name] SYSNAME + , [User_Name] SYSNAME + , [Login_Type] SYSNAME + , [Associated_Role] VARCHAR(MAX) + , [Create_Date] DATETIME + , [Modify_Date] DATETIME + ) + + INSERT @dbs_users + EXEC sp_MSforeachdb ' + USE [?] + SELECT + [Database_Name] = ''?'' + , [User_Name] = CASE dp.[name] WHEN ''dbo'' THEN (SELECT SUSER_SNAME([owner_sid]) FROM [master].[sys].[databases] WHERE [name] =''?'') ELSE dp.[name] END + , [Login_Type] = dp.[type_desc] + , [Associated_Role] = isnull(USER_NAME(dm.role_principal_id),'''') + , dp.[create_date] + , dp.[modify_date] + FROM + [sys].[database_principals] AS dp + LEFT JOIN [sys].[database_role_members] AS dm ON dp.[principal_id] = dm.[member_principal_id] + WHERE + 1=1 + AND dp.[sid] IS NOT NULL + AND dp.[sid] NOT IN (0x00) + AND dp.[is_fixed_role] != 1 + AND dp.[name] NOT LIKE ''##%''' + + SELECT + [Server_Name] = @@SERVERNAME + , [Database_Name] + , [User_Name] + , [Create_Date] + , [Modify_Date] + , [Permissions_User] = STUFF(( + SELECT ',' + CONVERT(VARCHAR(500), [Associated_Role]) + FROM @dbs_users AS dbu2 + WHERE dbu1.[Database_Name] = dbu2.[Database_Name] + AND dbu1.[User_Name] = dbu2.[User_Name] + FOR XML PATH('') + ), 1, 1, '') + , [CommandToRun] = 'USE [' + [Database_Name] + ']; DROP USER [' + [User_Name] + '];' + --, [Login_Type] + FROM + @dbs_users AS dbu1 + WHERE + 1=1 + AND [User_Name] NOT IN(SELECT [Login_Name] FROM #service_accounts) + AND [Login_Type] = 'WINDOWS_USER' + AND ([User_Name] = N'$(login_name)' OR N'$(login_name)' = N'') + GROUP BY + [Database_Name] + , [User_Name] + , [Create_Date] + , [Modify_Date] + --, [Login_Type] + ORDER BY + [Database_Name] + , [User_Name] + +PRINT '====================================================================='; +PRINT 'check agent jobs ... '; + + SELECT + [Server_Name] = @@SERVERNAME + , [SQL_Agent_Job_Name] = sj.[name] + , [Job_Owner] = sl.[name] + , [CommandToRun] = 'EXEC [msdb].[dbo].[sp_update_job] @job_id=N''' + CAST(sj.[job_id] AS VARCHAR(150)) + ''', @owner_login_name=N''sa'' ' + --, sj.[description] + --, sc.[name] + FROM + [msdb].[dbo].[sysjobs] AS sj + INNER JOIN [master].[sys].[syslogins] AS sl ON sj.[owner_sid] = sl.[sid] + INNER JOIN [msdb].[dbo].[syscategories] AS sc ON sc.[category_id] = sj.[category_id] + WHERE + 1=1 + AND sl.[Name] NOT IN(SELECT [Login_Name] FROM #service_accounts) + AND (sl.[name] = N'$(login_name)' OR N'$(login_name)' = N'') + ORDER BY + sj.[name] + +PRINT '====================================================================='; +PRINT 'check report subscriptions ... '; + + IF DB_ID('ReportServer') IS NOT NULL + WITH + service_account + AS + ( + SELECT [service_account_id] = [UserID], [UserName] FROM [ReportServer].[dbo].[Users] WHERE [UserName] = N'$(ssrs_service_account)' + ) + SELECT DISTINCT + [Server_Name] = @@SERVERNAME + , [Report_Name] = rp.[Name] + , [Subscription_Owner] = ou.[UserName] + , [Subscription_Owner_ID] = ou.[UserID] + , [CommandToRun] = 'UPDATE [ReportServer].[dbo].[Subscriptions] SET [OwnerID] = ''' + CAST((SELECT [service_account_id] FROM service_account) AS VARCHAR(MAX)) + ''' WHERE [OwnerID] = ''' + CAST(ou.[UserID] AS VARCHAR(MAX)) + '''' + --, sb.[Report_OID] + FROM + [ReportServer].[dbo].[Subscriptions] AS sb + INNER JOIN [ReportServer].[dbo].[Users] AS ou ON ou.[UserID] = sb.[OwnerID] + INNER JOIN [ReportServer].[dbo].[Catalog] AS rp ON rp.[ItemID] = sb.[Report_OID] + WHERE + 1=1 + AND ou.[UserName] NOT IN(SELECT [Login_Name] COLLATE Latin1_General_CI_AS FROM #service_accounts) + AND (ou.[UserName] = N'$(login_name)' OR N'$(login_name)' = N'') + + +PRINT '******* ROLLBACK TRANSACTION ******* '; +ROLLBACK TRANSACTION; + +--PRINT '******* COMMIT TRANSACTION ******* '; +--COMMIT TRANSACTION;