USE [NutsAndBolts] GO /****** Object: StoredProcedure [dbo].[alert_AlterFailedJobInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: auto alter failed schedule job info -- ============================================= CREATE PROCEDURE [dbo].[alert_AlterFailedJobInfo] @p_JobName VARCHAR(255) = NULL, -- Optional job name filter @p_ShowDisabled BIT = 0, -- Include disabled jobs? @p_ShowUnscheduled BIT = 0, -- Include Unscheduled jobs? @p_JobThresholdSec INT = 0, -- If positive, show only the jobs with LAST duration above this. @p_AvgExecThresholdSec INT = 0 -- If positive, show only the jobs with AVERAGE duration above this. AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT * INTO #TJob FROM ( SELECT JobName, ISNULL(LastStep,'') LastStep, CASE WHEN StartDate IS NOT NULL AND FinishDate IS NULL THEN 'Running' WHEN Enabled = 0 THEN 'Disabled' WHEN StepCount = 0 THEN 'No steps' WHEN RunStatus IS NOT NULL THEN RunStatus WHEN ScheduleCount = 0 THEN 'Not scheduled' ELSE 'UNKNOWN' END Info, DatabaseName, Enabled, ScheduleCount, StepCount, StartDate, FinishDate, DurationSec, RIGHT('0'+convert(varchar(5),DurationSec/3600),2)+':'+ RIGHT('0'+convert(varchar(5),DurationSec%3600/60),2)+':'+ RIGHT('0'+convert(varchar(5),(DurationSec%60)),2) DurationSecFormatted, avgDurationSec, RIGHT('0'+convert(varchar(5),avgDurationSec/3600),2)+':'+ RIGHT('0'+convert(varchar(5),avgDurationSec%3600/60),2)+':'+ RIGHT('0'+convert(varchar(5),(avgDurationSec%60)),2) avgDurationSecFormatted, CASE WHEN (DurationSec IS NULL OR ISNULL(avgDurationSec, 0) = 0) THEN 0 ELSE CONVERT(DECIMAL(18,2), (100*CAST(DurationSec AS DECIMAL)) / CAST (avgDurationSec as DECIMAL)) END AS DurationRatio, NextRunDate, StepCommand, HistoryMessage FROM ( SELECT j.name JobName, j.enabled Enabled, (SELECT COUNT(1) FROM msdb..sysjobschedules jss WHERE jss.job_id = j.job_id) ScheduleCount, (SELECT COUNT(1) FROM msdb..sysjobsteps jps WHERE jps.job_id = j.job_id) StepCount, ls1.job_history_id HistoryID, ls1.start_execution_date StartDate, ls1.stop_execution_date FinishDate, ls1.last_executed_step_id LastStepID, DATEDIFF(SECOND, ls1.start_execution_date, CASE WHEN ls1.stop_execution_date IS NULL THEN GETDATE() ELSE ls1.stop_execution_date END) DurationSec, ISNULL(avgSec, 0) avgDurationSec, ls1.next_scheduled_run_date NextRunDate, st.step_name LastStep, st.command StepCommand, st.database_name DatabaseName, h.message HistoryMessage, CASE WHEN h.job_id IS NULL THEN 'Never Run' ELSE CASE h.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded' WHEN 2 THEN 'Retry' WHEN 3 THEN 'Canceled' END END RunStatus, h.run_date rawRunDate, h.run_time rawRunTime, h.run_duration rawRunDuration FROM msdb..sysjobactivity ls1 (NOLOCK) INNER JOIN msdb..sysjobs j (NOLOCK) ON ls1.job_id = j.job_id INNER JOIN (SELECT job_id JobID, MAX(session_id) LastSessionID FROM msdb..sysjobactivity (NOLOCK) GROUP BY job_id ) ls2 ON ls1.job_id = ls2.JobID AND ls1.session_id = ls2.LastSessionID LEFT OUTER JOIN msdb..sysjobsteps st (NOLOCK) ON st.job_id = j.job_id AND ls1.last_executed_step_id = st.step_id LEFT OUTER JOIN msdb..sysjobhistory h (NOLOCK) ON h.instance_id = ls1.job_history_id LEFT OUTER JOIN ( SELECT j.job_id JobID, SUM(h.avgSecs) avgSec FROM msdb..sysjobs j (NOLOCK) INNER JOIN ( SELECT job_id, step_id, AVG(run_duration/10000*3600 + run_duration%10000/100*60 + run_duration%100) avgSecs FROM msdb..sysjobhistory WHERE step_id > 0 AND run_status = 1 GROUP BY job_id, step_id ) h ON j.job_id = h.job_id GROUP BY j.job_id ) jobavg ON jobavg.JobID = j.job_id )jj WHERE (@p_ShowDisabled = 1 OR (StartDate IS NOT NULL AND FinishDate IS NULL) OR Enabled = 1) AND (@p_JobName IS NULL OR JobName = @p_JobName) AND (@p_ShowUnscheduled = 1 OR (StartDate IS NOT NULL AND FinishDate IS NULL) OR ScheduleCount > 0) AND (@p_JobThresholdSec = 0 OR DurationSec >= @p_JobThresholdSec) AND (@p_AvgExecThresholdSec = 0 OR avgDurationSec >= @p_AvgExecThresholdSec))x ORDER BY CASE Info WHEN 'Running' THEN 0 WHEN 'Failed' THEN 1 WHEN 'Retry' THEN 2 WHEN 'Succeeded' THEN 3 WHEN 'Canceled' THEN 4 WHEN 'No steps' THEN 5 WHEN 'Not scheduled' THEN 6 WHEN 'Disabled' THEN 7 WHEN 'Never Run' THEN 8 WHEN 'UNKNOWN' THEN -1 ELSE -2 END, NextRunDate, JobName --send alert report part IF EXISTS(SELECT 1 FROM #TJob WHERE Info IN ('Failed') ) BEGIN SELECT * INTO #TReport FROM #TJob WHERE Info IN ('Failed') DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Alert Failed Job' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TJob END GO /****** Object: StoredProcedure [dbo].[dbm_KillInactiveConnection] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-06 -- Description: kill the inactive connection which last 1 minute -- ============================================= CREATE PROCEDURE [dbo].[dbm_KillInactiveConnection] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE cConnections CURSOR READ_ONLY FAST_FORWARD FOR SELECT spid FROM master..sysprocesses p INNER JOIN master..syslogins l ON p.sid = l.sid WHERE l.loginname LIKE 'MSDOMAIN1\%' AND l.loginname NOT IN ('MSDOMAIN1\xzhang3', 'MSDOMAIN1\ouli', 'MSDOMAIN1\atian1') AND p.last_batch <= DATEADD(mi, -1, GETDATE()) DECLARE @l_ConnectionId INT, @l_Sql VARCHAR(100) OPEN cConnections WHILE 1 = 1 BEGIN FETCH NEXT FROM cConnections INTO @l_ConnectionId IF @@FETCH_STATUS <> 0 BREAK SET @l_Sql = 'KILL ' + CONVERT(VARCHAR, @l_ConnectionId) EXECUTE( @l_Sql ) END CLOSE cConnections DEALLOCATE cConnections END GO /****** Object: StoredProcedure [dbo].[demo_EmailHtmlTableAlert] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- Purpose: a template for sending alert script part -- Create Date: 08/29/2012 -- Last Update: 08/29/2012 -- Author: Alex Tian CREATE PROCEDURE [dbo].[demo_EmailHtmlTableAlert] AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED --generate a temp table SELECT TOP 10 * INTO #TAlert FROM master.sys.objects DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailObject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailObject='demo_EmailHtmlTableAlert' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.Fn_splitstringtoquerycolumn(@l_TColumn, ',') SET @l_HHeader=dbo.Fn_splitstringtohtmlheader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE Sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.Fn_formathtmltable(@l_Html, @l_HHeader) EXECUTE dbo.Utility_emailhtmlstringtohtmltable @p_Subject=@l_EmailObject, @p_HtmlString=@l_EmailBody END GO /****** Object: StoredProcedure [dbo].[rpt_ReportIndexFragementInfoForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: report frgement info for all databases on a given server -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportIndexFragementInfoForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED CREATE TABLE #FragmentedIndexes ( DatabaseName NVARCHAR(200), SchemaName NVARCHAR(200), TableName NVARCHAR(200), IndexName NVARCHAR(200), [Fragmentation%] FLOAT ) EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #FragmentedIndexes SELECT DB_NAME(DB_ID()) AS DatabaseName, sc.name AS SchemaName, OBJECT_NAME (s.object_id) AS TableName, i.name AS IndexName, s.avg_fragmentation_in_percent AS [Fragmentation%] FROM sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL,''SAMPLED'') s INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id INNER JOIN sys.objects o ON s.object_id = o.object_id INNER JOIN sys.schemas sc ON sc.[schema_id] = o.[schema_id] WHERE s.database_id = DB_ID() AND i.index_id != 0 AND s.record_count > 0 AND s.avg_fragmentation_in_percent>5 AND o.is_ms_shipped = 0 ;' --Generate rebuild/reorganize index script SELECT CASE WHEN [Fragmentation%] > 30 THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' REBUILD;' WHEN [Fragmentation%] > 10 THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' REORGANIZE;' END AS MaintanceScript INTO #TScript FROM #FragmentedIndexes WHERE [Fragmentation%] > 10 --send alert report part IF EXISTS(SELECT 1 FROM #FragmentedIndexes WHERE [Fragmentation%]>=10 ) BEGIN SELECT * INTO #TReport FROM #FragmentedIndexes WHERE [Fragmentation%]>=10 SELECT * INTO #TReport1 FROM #TScript DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) --for #TReport part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Index Fragement List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody --for #TReport1 part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Index Fragement Maintance Script For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport1') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport1 AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport DROP TABLE #TReport1 END DROP TABLE #FragmentedIndexes DROP TABLE #TScript END GO /****** Object: StoredProcedure [dbo].[rpt_ReportJobSummaryInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get job summary -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportJobSummaryInfo] @p_JobName VARCHAR(255) = NULL, -- Optional job name filter @p_ShowDisabled BIT = 0, -- Include disabled jobs? @p_ShowUnscheduled BIT = 0, -- Include Unscheduled jobs? @p_JobThresholdSec INT = 0, -- If positive, show only the jobs with LAST duration above this. @p_AvgExecThresholdSec INT = 0 -- If positive, show only the jobs with AVERAGE duration above this. AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT * INTO #TJob FROM ( SELECT JobName, ISNULL(LastStep,'') LastStep, CASE WHEN StartDate IS NOT NULL AND FinishDate IS NULL THEN 'Running' WHEN Enabled = 0 THEN 'Disabled' WHEN StepCount = 0 THEN 'No steps' WHEN RunStatus IS NOT NULL THEN RunStatus WHEN ScheduleCount = 0 THEN 'Not scheduled' ELSE 'UNKNOWN' END Info, DatabaseName, Enabled, ScheduleCount, StepCount, StartDate, FinishDate, DurationSec, RIGHT('0'+convert(varchar(5),DurationSec/3600),2)+':'+ RIGHT('0'+convert(varchar(5),DurationSec%3600/60),2)+':'+ RIGHT('0'+convert(varchar(5),(DurationSec%60)),2) DurationSecFormatted, avgDurationSec, RIGHT('0'+convert(varchar(5),avgDurationSec/3600),2)+':'+ RIGHT('0'+convert(varchar(5),avgDurationSec%3600/60),2)+':'+ RIGHT('0'+convert(varchar(5),(avgDurationSec%60)),2) avgDurationSecFormatted, CASE WHEN (DurationSec IS NULL OR ISNULL(avgDurationSec, 0) = 0) THEN 0 ELSE CONVERT(DECIMAL(18,2), (100*CAST(DurationSec AS DECIMAL)) / CAST (avgDurationSec as DECIMAL)) END AS DurationRatio, NextRunDate, StepCommand, HistoryMessage FROM ( SELECT j.name JobName, j.enabled Enabled, (SELECT COUNT(1) FROM msdb..sysjobschedules jss WHERE jss.job_id = j.job_id) ScheduleCount, (SELECT COUNT(1) FROM msdb..sysjobsteps jps WHERE jps.job_id = j.job_id) StepCount, ls1.job_history_id HistoryID, ls1.start_execution_date StartDate, ls1.stop_execution_date FinishDate, ls1.last_executed_step_id LastStepID, DATEDIFF(SECOND, ls1.start_execution_date, CASE WHEN ls1.stop_execution_date IS NULL THEN GETDATE() ELSE ls1.stop_execution_date END) DurationSec, ISNULL(avgSec, 0) avgDurationSec, ls1.next_scheduled_run_date NextRunDate, st.step_name LastStep, st.command StepCommand, st.database_name DatabaseName, h.message HistoryMessage, CASE WHEN h.job_id IS NULL THEN 'Never Run' ELSE CASE h.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded' WHEN 2 THEN 'Retry' WHEN 3 THEN 'Canceled' END END RunStatus, h.run_date rawRunDate, h.run_time rawRunTime, h.run_duration rawRunDuration FROM msdb..sysjobactivity ls1 (NOLOCK) INNER JOIN msdb..sysjobs j (NOLOCK) ON ls1.job_id = j.job_id INNER JOIN (SELECT job_id JobID, MAX(session_id) LastSessionID FROM msdb..sysjobactivity (NOLOCK) GROUP BY job_id ) ls2 ON ls1.job_id = ls2.JobID AND ls1.session_id = ls2.LastSessionID LEFT OUTER JOIN msdb..sysjobsteps st (NOLOCK) ON st.job_id = j.job_id AND ls1.last_executed_step_id = st.step_id LEFT OUTER JOIN msdb..sysjobhistory h (NOLOCK) ON h.instance_id = ls1.job_history_id LEFT OUTER JOIN ( SELECT j.job_id JobID, SUM(h.avgSecs) avgSec FROM msdb..sysjobs j (NOLOCK) INNER JOIN ( SELECT job_id, step_id, AVG(run_duration/10000*3600 + run_duration%10000/100*60 + run_duration%100) avgSecs FROM msdb..sysjobhistory WHERE step_id > 0 AND run_status = 1 GROUP BY job_id, step_id ) h ON j.job_id = h.job_id GROUP BY j.job_id ) jobavg ON jobavg.JobID = j.job_id )jj WHERE (@p_ShowDisabled = 1 OR (StartDate IS NOT NULL AND FinishDate IS NULL) OR Enabled = 1) AND (@p_JobName IS NULL OR JobName = @p_JobName) AND (@p_ShowUnscheduled = 1 OR (StartDate IS NOT NULL AND FinishDate IS NULL) OR ScheduleCount > 0) AND (@p_JobThresholdSec = 0 OR DurationSec >= @p_JobThresholdSec) AND (@p_AvgExecThresholdSec = 0 OR avgDurationSec >= @p_AvgExecThresholdSec))x ORDER BY CASE Info WHEN 'Running' THEN 0 WHEN 'Failed' THEN 1 WHEN 'Retry' THEN 2 WHEN 'Succeeded' THEN 3 WHEN 'Canceled' THEN 4 WHEN 'No steps' THEN 5 WHEN 'Not scheduled' THEN 6 WHEN 'Disabled' THEN 7 WHEN 'Never Run' THEN 8 WHEN 'UNKNOWN' THEN -1 ELSE -2 END, NextRunDate, JobName --send alert report part IF EXISTS(SELECT 1 FROM #TJob ) BEGIN SELECT * INTO #TReport FROM #TJob DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Job Summary' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TJob END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopLongestBlockedQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report the queries spend the longest time being blocked for all database -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopLongestBlockedQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 CAST((qs.total_elapsed_time - qs.total_worker_time) /1000000.0 AS DECIMAL(28,2)) AS [Total time blocked (s)], CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time AS DECIMAL(28,2)) AS [% CPU], CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting], qs.execution_count, CAST((qs.total_elapsed_time - qs.total_worker_time) / 1000000.0/ qs.execution_count AS DECIMAL(28, 2)) AS [Blocking average (s)], SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName --qp.query_plan INTO #TResult FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_elapsed_time > 0 ORDER BY [Total time blocked (s)] DESC --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top Longest Blocked Query List' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopLongestTimeQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: The queries that take the longest time to run for all database -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopLongestTimeQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 CAST(qs.total_elapsed_time / 1000000.0 AS DECIMAL(28, 2))AS [Total Duration (s)], CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time AS DECIMAL(28, 2))AS [% CPU], CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting], qs.execution_count, CAST(qs.total_elapsed_time / 1000000.0 / qs.execution_count AS DECIMAL(28, 2))AS [Average Duration (s)], SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName --qp.query_plan INTO #TResult FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_elapsed_time > 0 ORDER BY qs.total_elapsed_time DESC --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top Longest Time Cost Query List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopMissingIndexForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report the top missing index for all database -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopMissingIndexForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 'CREATE NONCLUSTERED INDEX '+ QUOTENAME('IX_AutoGenerated_'+ REPLACE(REPLACE(CONVERT(VARCHAR(25), GETDATE(), 113), ' ', '_'), ':', '_')+ '_' + CAST(d.index_handle AS VARCHAR(22)))+ ' ON ' + d.[statement] + '('+ CASE WHEN d.equality_columns IS NULL THEN d.inequality_columns WHEN d.inequality_columns IS NULL THEN d.equality_columns ELSE d.equality_columns + ',' + d.inequality_columns END + ')'+ CASE WHEN d.included_columns IS NOT NULL THEN ' INCLUDE ( ' + d.included_columns + ')' ELSE '' END AS MissingIndexSQL, ROUND(s.avg_total_user_cost * s.avg_user_impact * (s.user_seeks + s.user_scans),0) AS [Total Cost], d.[statement] AS [Table Name], d.equality_columns, d.inequality_columns, d.included_columns INTO #MissingIndexes FROM sys.dm_db_missing_index_groups g INNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle INNER JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle ORDER BY [Total Cost] DESC SELECT MissingIndexSQL AS MaintanceScript INTO #TScript FROM #MissingIndexes --send alert report part IF EXISTS(SELECT 1 FROM #MissingIndexes) BEGIN SELECT * INTO #TAlert FROM #MissingIndexes SELECT * INTO #TAlert1 FROM #TScript DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) --for #TAlert part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top Missing Index List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody --for #TAlert1 part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top Missing Index Maintance Script For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert1') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert1 AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TAlert DROP TABLE #TAlert1 END DROP TABLE #MissingIndexes DROP TABLE #TScript END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopMostCPUCostQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report the queries that use the most CPU for all database -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopMostCPUCostQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 CAST((qs.total_worker_time) / 1000000.0AS DECIMAL(28,2)) AS [Total CPU time (s)], CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time AS DECIMAL(28,2)) AS [% CPU], CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting], qs.execution_count, CAST((qs.total_worker_time) / 1000000.0/ qs.execution_count AS DECIMAL(28, 2)) AS [CPU time average (s)], SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName --qp.query_plan INTO #TResult FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_elapsed_time > 0 ORDER BY [Total CPU time (s)] DESC --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top More CUP Cost Query List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopMostIOCostQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report the queries that use the most I/O -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopMostIOCostQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 [Total IO] = (qs.total_logical_reads + qs.total_logical_writes), [Average IO] = (qs.total_logical_reads + qs.total_logical_writes) /qs.execution_count, qs.execution_count, SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName --qp.query_plan INTO #TResult FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY [Total IO] DESC --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top More IO Cost Query List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopMostOftenExecutedQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report the queries that have been executed the most often -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopMostOftenExecutedQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 qs.execution_count, SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName --qp.query_plan INTO #TResult FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY qs.execution_count DESC; --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top More Most Often Executed Query List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportTopMostRecompiledQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report the most-recompiled queries -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportTopMostRecompiledQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 qs.plan_generation_num, qs.total_elapsed_time, qs.execution_count, SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DBName, qs.creation_time, qs.last_execution_time INTO #TResult FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt ORDER BY plan_generation_num DESC --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Top More Most Recompiled Query List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportUnusedIndexForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Report unused indexes for all database -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportUnusedIndexForAllDatabase] AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SET NOCOUNT ON SELECT DB_NAME() AS DatabaseName, SCHEMA_NAME(o.Schema_ID) AS SchemaName, OBJECT_NAME(s.[object_id]) AS TableName, i.name AS IndexName, s.user_updates, s.system_seeks + s.system_scans + s.system_lookups AS [System usage] INTO #TempUnusedIndexes FROM sys.dm_db_index_usage_stats s INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id INNER JOIN sys.objects o ON i.object_id = o.object_id WHERE 1=2 EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #TempUnusedIndexes SELECT TOP 20 DB_NAME() AS DatabaseName, SCHEMA_NAME(o.Schema_ID) AS SchemaName, OBJECT_NAME(s.[object_id]) AS TableName, i.name AS IndexName, s.user_updates, s.system_seeks + s.system_scans + s.system_lookups AS [System usage] FROM sys.dm_db_index_usage_stats s INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id INNER JOIN sys.objects o ON i.object_id = o.object_id WHERE s.database_id = DB_ID() AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 AND user_seeks = 0 AND user_scans = 0 AND user_lookups = 0 AND i.name IS NOT NULL ORDER BY user_updates DESC' DECLARE @DisableOrDrop INT DECLARE @DisableIndexesSQL NVARCHAR(MAX) SET @DisableOrDrop = 1 SET @DisableIndexesSQL = '' SELECT CASE WHEN @DisableOrDrop = 1 THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' DISABLE;' ELSE CHAR(10) + 'DROP INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) END AS MaintanceScript INTO #TScript FROM #TempUnusedIndexes --send alert report part IF EXISTS(SELECT 1 FROM #TempUnusedIndexes ) BEGIN SELECT * INTO #TReport FROM #TempUnusedIndexes SELECT * INTO #TReport1 FROM #TScript DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) --for #TReport part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Unused Index List For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody --for #TReport1 part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Unused Index Maintance Script For All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport1') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport1 AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport DROP TABLE #TReport1 END DROP TABLE #TempUnusedIndexes DROP TABLE #TScript END GO /****** Object: StoredProcedure [dbo].[rpt_ReportWeeklyBackupEvaluationForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get backup evaluated info for all database -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportWeeklyBackupEvaluationForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT a.server_name AS 'Server', a.database_name AS 'Database', CONVERT(VARCHAR(25), a.backup_start_date,100) AS 'Start Date', CONVERT(VARCHAR(25), a.backup_finish_date,100) AS 'Finish Date', DATENAME(WEEKDAY, a.backup_finish_date) AS 'Day' , DATEDIFF(MILLISECOND , a.backup_start_date, a.backup_finish_date) AS 'MSec' , DATEDIFF(SECOND, a.backup_start_date, a.backup_finish_date) AS 'Sec' , DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) AS 'Mins' , CAST(CAST(DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) AS DECIMAL(8,3))/60 AS DECIMAL(8,1)) AS 'Hours', CASE WHEN DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) > 0 THEN CAST(CEILING(a.backup_size /1048576) / DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) AS DECIMAL(8,1)) ELSE 0 END AS 'Meg/Min', CEILING(a.backup_size /1048576) AS 'Size Meg', CAST((a.backup_size /1073741824) AS DECIMAL(9,2)) AS 'Gig', a.user_name,a.backup_size AS 'Raw Size' INTO #TResult FROM msdb.dbo.backupset a JOIN msdb.dbo.backupset b ON a.server_name = b.server_name AND a.database_name = b.database_name WHERE a.type = 'D' AND b.type = 'D' AND DATEDIFF(WEEKDAY,a.backup_start_date,GETDATE())<=7 GROUP BY a.server_name, a.database_name, a.backup_start_date, a.backup_finish_date, a.backup_size, a.user_name ORDER BY a.server_name DESC , a.database_name,a.backup_start_date DESC --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report The Lastest Week Backup Evaluation' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportWeeklyDiskSpaceTrend] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /****** Object: StoredProcedure [dbo].[rpt_ReportTheLatestWeekEventLog] Script Date: 2012/9/6 17:29:49 ******/ -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: auto report daily disk space trend -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportWeeklyDiskSpaceTrend] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_BeginDate SMALLDATETIME DECLARE @l_EndDate SMALLDATETIME DECLARE @l_DateNow SMALLDATETIME SET @l_DateNow = CONVERT(VARCHAR(10), GETDATE(), 120) SET @l_BeginDate = DATEADD(d, - DATEPART(dw, @l_DateNow) - 7, @l_DateNow) SET @l_EndDate = DATEADD(d, - DATEPART(dw, @l_DateNow), @l_DateNow) IF EXISTS ( SELECT 1 FROM dbo.AvailableDiskSpace WHERE LastUpdate >= @l_BeginDate AND LastUpdate < @l_EndDate ) BEGIN SELECT * INTO #TResult FROM dbo.AvailableDiskSpace WHERE LastUpdate >= @l_BeginDate AND LastUpdate < @l_EndDate ORDER BY DriveLetter,LastUpdate DESC END ELSE RETURN 0 --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Daily Disk Space Trend' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[rpt_ReportWeeklyEventLog] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: auto report event logs -- ============================================= CREATE PROCEDURE [dbo].[rpt_ReportWeeklyEventLog] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_BeginDate SMALLDATETIME DECLARE @l_EndDate SMALLDATETIME DECLARE @l_DateNow SMALLDATETIME SET @l_DateNow = CONVERT(VARCHAR(10), GETDATE(), 120) SET @l_BeginDate = DATEADD(d, - DATEPART(dw, @l_DateNow) - 7, @l_DateNow) SET @l_EndDate = DATEADD(d, - DATEPART(dw, @l_DateNow), @l_DateNow) IF EXISTS ( SELECT 1 FROM dbo.EventLog WHERE EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'smalldatetime') >= @l_BeginDate AND EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'smalldatetime') < @l_EndDate ) BEGIN SELECT EventData.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'varchar(128)') AS DatabaseName, EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'varchar(128)') AS EventType, EventData.value('(/EVENT_INSTANCE/UserName)[1]', 'varchar(128)') AS UserName, EventData.value('(/EVENT_INSTANCE/LoginName)[1]', 'varchar(128)') AS LoginName, EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'datetime') AS PostTime, EventData.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)') AS CommandText INTO #TResult FROM dbo.EventLog WHERE EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'smalldatetime') >= @l_BeginDate AND EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'smalldatetime') < @l_EndDate END ELSE RETURN 0 --send alert report part IF EXISTS(SELECT 1 FROM #TResult ) BEGIN SELECT * INTO #TReport FROM #TResult DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Auto Report Latest Event Log' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TReport') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TReport AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TReport END DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[utility_AUDIT_CheckDefaultStatisticsOptionForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Check statistics option default value -- ============================================= CREATE PROCEDURE [dbo].[utility_AUDIT_CheckDefaultStatisticsOptionForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT name AS DatabaseName, is_auto_create_stats_on AS AutoCreateStatistics, is_auto_update_stats_on AS AutoUpdateStatistics, is_auto_update_stats_async_on AS AutoUpdateStatisticsAsync FROM sys.databases ORDER BY DatabaseName END GO /****** Object: StoredProcedure [dbo].[utility_AUDIT_CheckDisparateColumWithDifferentDataTypeForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Find disparate columns with different data types -- ============================================= CREATE PROCEDURE [dbo].[utility_AUDIT_CheckDisparateColumWithDifferentDataTypeForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DISTINCT DB_NAME() AS DBName, C1.COLUMN_NAME, C1.TABLE_SCHEMA, C1.TABLE_NAME, C1.DATA_TYPE, C1.CHARACTER_MAXIMUM_LENGTH, C1.NUMERIC_PRECISION, C1.NUMERIC_SCALE, 0 AS [%] INTO #TResult FROM INFORMATION_SCHEMA.COLUMNS C1 INNER JOIN INFORMATION_SCHEMA.COLUMNS C2 ON C1.COLUMN_NAME = C2.COLUMN_NAME WHERE 1=2 EXEC sp_MSforeachdb 'USE [?]; SELECT COLUMN_NAME, [%] = CONVERT(DECIMAL(12,2),COUNT(COLUMN_NAME)*100.0 / COUNT(*)OVER()) INTO #Prevalence FROM INFORMATION_SCHEMA.COLUMNS GROUP BY COLUMN_NAME INSERT INTO #TResult SELECT DISTINCT DB_NAME() AS DBName, C1.COLUMN_NAME, C1.TABLE_SCHEMA, C1.TABLE_NAME, C1.DATA_TYPE, C1.CHARACTER_MAXIMUM_LENGTH, C1.NUMERIC_PRECISION, C1.NUMERIC_SCALE, [%] FROM INFORMATION_SCHEMA.COLUMNS C1 INNER JOIN INFORMATION_SCHEMA.COLUMNS C2 ON C1.COLUMN_NAME = C2.COLUMN_NAME INNER JOIN #Prevalence p ON p.COLUMN_NAME = C1.COLUMN_NAME WHERE ((C1.DATA_TYPE != C2.DATA_TYPE) OR (C1.CHARACTER_MAXIMUM_LENGTH != C2.CHARACTER_MAXIMUM_LENGTH) OR (C1.NUMERIC_PRECISION != C2.NUMERIC_PRECISION) OR (C1.NUMERIC_SCALE != C2.NUMERIC_SCALE)) ORDER BY [%] DESC, C1.COLUMN_NAME, C1.TABLE_SCHEMA, C1.TABLE_NAME ;' SELECT * FROM #TResult DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[utility_AUDIT_CheckIdentityColumnInfoForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Check identity column info for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_AUDIT_CheckIdentityColumnInfoForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DB_NAME() AS DBName, QUOTENAME(SCHEMA_NAME(t.schema_id)) + '.' + QUOTENAME(t.name) AS TableName, c.name AS ColumnName, CASE c.system_type_id WHEN 127 THEN 'bigint' WHEN 56 THEN 'int' WHEN 52 THEN 'smallint' WHEN 48 THEN 'tinyint' END AS DataType, IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + '.' + t.name) AS CurrentIdentityValue, CASE c.system_type_id WHEN 127 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + '.' + t.name) * 100.) / 9223372036854775807 WHEN 56 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + '.' + t.name) * 100.) / 2147483647 WHEN 52 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + '.' + t.name) * 100.) / 32767 WHEN 48 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + '.' + t.name) * 100.) / 255 END AS PercentageUsed INTO #TResult FROM sys.columns AS c INNER JOIN sys.tables AS t ON t.[object_id] = c.[object_id] WHERE 1=2 EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #TResult SELECT DB_NAME() AS DBName, QUOTENAME(SCHEMA_NAME(t.schema_id)) + ''.'' + QUOTENAME(t.name) AS TableName, c.name AS ColumnName, CASE c.system_type_id WHEN 127 THEN ''bigint'' WHEN 56 THEN ''int'' WHEN 52 THEN ''smallint'' WHEN 48 THEN ''tinyint'' END AS DataType, IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + ''.'' + t.name) AS CurrentIdentityValue, CASE c.system_type_id WHEN 127 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + ''.'' + t.name) * 100.) / 9223372036854775807 WHEN 56 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + ''.'' + t.name) * 100.) / 2147483647 WHEN 52 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + ''.'' + t.name) * 100.) / 32767 WHEN 48 THEN (IDENT_CURRENT(SCHEMA_NAME(t.schema_id) + ''.'' + t.name) * 100.) / 255 END AS PercentageUsed FROM sys.columns AS c INNER JOIN sys.tables AS t ON t.[object_id] = c.[object_id] WHERE c.is_identity = 1 ORDER BY PercentageUsed DESC;' SELECT * FROM #TResult ORDER BY DBName DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[utility_AUDIT_CheckTableWithoutClusteredIndexForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Find the tables without clustered index for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_AUDIT_CheckTableWithoutClusteredIndexForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DB_NAME() AS DBName, o.name INTO #TResult FROM sys.objects o WHERE 1=2 EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #TResult SELECT DB_NAME() AS DBName, o.name FROM sys.objects o WHERE o.type=''U'' AND NOT EXISTS(SELECT 1 FROM sys.indexes i WHERE o.object_id = i.object_id AND i.type_desc = ''CLUSTERED'');' SELECT * FROM #TResult DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[utility_BACKUP_GetWeeklyBackupEvaluatedInfoForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get backup evaluated info for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_BACKUP_GetWeeklyBackupEvaluatedInfoForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT a.server_name AS 'Server', a.database_name AS 'Database', CONVERT(VARCHAR(25), a.backup_start_date,100) AS 'Start Date', CONVERT(VARCHAR(25), a.backup_finish_date,100) AS 'Finish Date', DATENAME(WEEKDAY, a.backup_finish_date) AS 'Day' , DATEDIFF(MILLISECOND , a.backup_start_date, a.backup_finish_date) AS 'MSec' , DATEDIFF(SECOND, a.backup_start_date, a.backup_finish_date) AS 'Sec' , DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) AS 'Mins' , CAST(CAST(DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) AS DECIMAL(8,3))/60 AS DECIMAL(8,1)) AS 'Hours', CASE WHEN DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) > 0 THEN CAST(CEILING(a.backup_size /1048576) / DATEDIFF(MINUTE, a.backup_start_date, a.backup_finish_date) AS DECIMAL(8,1)) ELSE 0 END AS 'Meg/Min', CEILING(a.backup_size /1048576) AS 'Size Meg', CAST((a.backup_size /1073741824) AS DECIMAL(9,2)) AS 'Gig', a.user_name,a.backup_size AS 'Raw Size' FROM msdb.dbo.backupset a JOIN msdb.dbo.backupset b ON a.server_name = b.server_name AND a.database_name = b.database_name WHERE a.type = 'D' AND b.type = 'D' AND DATEDIFF(WEEKDAY,a.backup_start_date,GETDATE())<=7 GROUP BY a.server_name, a.database_name, a.backup_start_date, a.backup_finish_date, a.backup_size, a.user_name ORDER BY a.server_name DESC , a.database_name,a.backup_start_date DESC END GO /****** Object: StoredProcedure [dbo].[utility_BASIC_GetCPUUsageBasicInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get CPU usage basic info -- ============================================= CREATE PROCEDURE [dbo].[utility_BASIC_GetCPUUsageBasicInfo] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @ts_now BIGINT SELECT @ts_now = cpu_ticks / CONVERT(FLOAT, cpu_ticks_in_ms) FROM sys.dm_os_sys_info SELECT RecordId, DATEADD(ms, -1 * (@ts_now - [timestamp]), GETDATE()) AS EventTime, SQLProcessUtilization, SystemIdle, 100 - SystemIdle - SQLProcessUtilization AS OtherProcessUtilization FROM ( SELECT timestamp, record.value('(./Record/@id)[1]', 'int') AS RecordId, record.value('(./Record/SchedulerMonitorEvent/SystemHealth/SystemIdle)[1]', 'int') AS SystemIdle, record.value('(./Record/SchedulerMonitorEvent/SystemHealth/ProcessUtilization)[1]', 'int') AS SQLProcessUtilization FROM (SELECT timestamp, CONVERT(XML, record) AS record FROM sys.dm_os_ring_buffers WHERE ring_buffer_type = N'RING_BUFFER_SCHEDULER_MONITOR' AND record LIKE '% %') AS x ) AS y ORDER BY RecordId DESC END GO /****** Object: StoredProcedure [dbo].[utility_BASIC_GetDatabaseBasicInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get database basic info -- ============================================= CREATE PROCEDURE [dbo].[utility_BASIC_GetDatabaseBasicInfo] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED IF EXISTS ( SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[HoldforEachDB]') ) DROP TABLE [tempdb].[dbo].[HoldforEachDB] CREATE TABLE [tempdb].[dbo].[HoldforEachDB] ( [Server] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [DatabaseName] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [Size] [int] NOT NULL, [File_Status] [int] NULL, [Name] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [Filename] [nvarchar](260) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL, [Status] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [Updateability] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [User_Access] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL, [Recovery] [nvarchar](128) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ) ON [PRIMARY] INSERT INTO [tempdb].[dbo].[HoldforEachDB] EXEC sp_MSforeachdb 'SELECT CONVERT(char(100), SERVERPROPERTY(''Servername'')) AS Server, ''?'' AS DatabaseName, [?]..sysfiles.size, [?]..sysfiles.status, [?]..sysfiles.name, [?]..sysfiles.filename, CONVERT(sysname,DatabasePropertyEx(''?'',''Status'')) AS Status, CONVERT(sysname,DatabasePropertyEx(''?'',''Updateability'')) AS Updateability, CONVERT(sysname,DatabasePropertyEx(''?'',''UserAccess'')) AS User_Access, CONVERT(sysname,DatabasePropertyEx(''?'',''Recovery'')) AS Recovery From [?]..sysfiles' SELECT * FROM [tempdb].[dbo].[HoldforEachDB] ORDER BY DatabaseName DROP TABLE [tempdb].[dbo].[HoldforEachDB] END GO /****** Object: StoredProcedure [dbo].[utility_BASIC_GetSecurityBasicInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get security basic info -- ============================================= CREATE PROCEDURE [dbo].[utility_BASIC_GetSecurityBasicInfo] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED IF EXISTS ( SELECT * FROM tempdb.dbo.sysobjects WHERE id = OBJECT_ID(N'[tempdb].[dbo].[SQL_DB_REP]') ) DROP TABLE [tempdb].[dbo].[SQL_DB_REP] ; CREATE TABLE [tempdb].[dbo].[SQL_DB_REP] ( [Server] [varchar](100) NOT NULL, [DB_Name] [varchar](70) NOT NULL, [User_Name] [nvarchar](90) NULL, [Group_Name] [varchar](100) NULL, [Account_Type] [varchar](22) NULL, [Login_Name] [varchar](80) NULL, [Def_DB] [varchar](100) NULL ) ON [PRIMARY] INSERT INTO [tempdb].[dbo].[SQL_DB_REP] EXEC sp_MSforeachdb 'SELECT CONVERT(varchar(100), SERVERPROPERTY(''Servername'')) AS Server, ''?'' AS DB_Name, usu.name u_name, CASE WHEN (usg.uid is null) THEN ''public'' ELSE usg.name END as Group_Name, CASE WHEN usu.isntuser=1 THEN ''Windows Domain Account'' WHEN usu.isntgroup = 1 THEN ''Windows Group'' WHEN usu.issqluser = 1 THEN''SQL Account'' WHEN usu.issqlrole = 1 THEN ''SQL Role'' END as Account_Type, lo.loginname, lo.dbname AS Def_DB FROM [?]..sysusers usu LEFT OUTER JOIN([?]..sysmembers mem INNER JOIN [?]..sysusers usg ON mem.groupuid = usg.uid) ON usu.uid = mem.memberuid LEFT OUTER JOIN master.dbo.syslogins lo ON usu.sid = lo.sid WHERE ( usu.islogin = 1 AND usu.isaliased = 0 AND usu.hasdbaccess = 1) AND (usg.issqlrole = 1 OR usg.uid is null)' SELECT * FROM [tempdb].[dbo].[SQL_DB_REP] ORDER BY [DB_Name] DROP TABLE [tempdb].[dbo].[SQL_DB_REP] END GO /****** Object: StoredProcedure [dbo].[utility_BASIC_GetServerBasicInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get database server basic info -- ============================================= CREATE PROCEDURE [dbo].[utility_BASIC_GetServerBasicInfo] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS Server, CONVERT(CHAR(100), SERVERPROPERTY('ProductVersion')) AS ProductVersion, CONVERT(CHAR(100), SERVERPROPERTY('ProductLevel')) AS ProductLevel, CONVERT(CHAR(100), SERVERPROPERTY('ResourceLastUpdateDateTime')) AS ResourceLastUpdateDateTime, CONVERT(CHAR(100), SERVERPROPERTY('ResourceVersion')) AS ResourceVersion, CASE WHEN SERVERPROPERTY('IsIntegratedSecurityOnly') = 1 THEN 'Integrated security' WHEN SERVERPROPERTY('IsIntegratedSecurityOnly') = 0 THEN 'Not Integrated security' END AS IsIntegratedSecurityOnly, CASE WHEN SERVERPROPERTY('EngineEdition') = 1 THEN 'Personal Edition' WHEN SERVERPROPERTY('EngineEdition') = 2 THEN 'Standard Edition' WHEN SERVERPROPERTY('EngineEdition') = 3 THEN 'Enterprise Edition' WHEN SERVERPROPERTY('EngineEdition') = 4 THEN 'Express Edition' END AS EngineEdition, CONVERT(CHAR(100), SERVERPROPERTY('InstanceName')) AS InstanceName, CONVERT(CHAR(100), SERVERPROPERTY('ComputerNamePhysicalNetBIOS')) AS ComputerNamePhysicalNetBIOS, CONVERT(CHAR(100), SERVERPROPERTY('LicenseType')) AS LicenseType, CONVERT(CHAR(100), SERVERPROPERTY('NumLicenses')) AS NumLicenses, CONVERT(CHAR(100), SERVERPROPERTY('BuildClrVersion')) AS BuildClrVersion, CONVERT(CHAR(100), SERVERPROPERTY('Collation')) AS Collation, CONVERT(CHAR(100), SERVERPROPERTY('CollationID')) AS CollationID, CONVERT(CHAR(100), SERVERPROPERTY('ComparisonStyle')) AS ComparisonStyle, CASE WHEN CONVERT(CHAR(100), SERVERPROPERTY('EditionID')) = -1253826760 THEN 'Desktop Edition' WHEN SERVERPROPERTY('EditionID') = -1592396055 THEN 'Express Edition' WHEN SERVERPROPERTY('EditionID') = -1534726760 THEN 'Standard Edition' WHEN SERVERPROPERTY('EditionID') = 1333529388 THEN 'Workgroup Edition' WHEN SERVERPROPERTY('EditionID') = 1804890536 THEN 'Enterprise Edition' WHEN SERVERPROPERTY('EditionID') = -323382091 THEN 'Personal Edition' WHEN SERVERPROPERTY('EditionID') = -2117995310 THEN 'Developer Edition' WHEN SERVERPROPERTY('EditionID') = 610778273 THEN 'Enterprise Evaluation Edition' WHEN SERVERPROPERTY('EditionID') = 1044790755 THEN 'Windows Embedded SQL' WHEN SERVERPROPERTY('EditionID') = 4161255391 THEN 'Express Edition with Advanced Services' END AS ProductEdition, CASE WHEN CONVERT(CHAR(100), SERVERPROPERTY('IsClustered')) = 1 THEN 'Clustered' WHEN SERVERPROPERTY('IsClustered') = 0 THEN 'Not Clustered' WHEN SERVERPROPERTY('IsClustered') = NULL THEN 'Error' END AS IsClustered, CASE WHEN CONVERT(CHAR(100), SERVERPROPERTY('IsFullTextInstalled')) = 1 THEN 'Full-text is installed' WHEN SERVERPROPERTY('IsFullTextInstalled') = 0 THEN 'Full-text is not installed' WHEN SERVERPROPERTY('IsFullTextInstalled') = NULL THEN 'Error' END AS IsFullTextInstalled, CONVERT(CHAR(100), SERVERPROPERTY('SqlCharSet')) AS SqlCharSet, CONVERT(CHAR(100), SERVERPROPERTY('SqlCharSetName')) AS SqlCharSetName, CONVERT(CHAR(100), SERVERPROPERTY('SqlSortOrder')) AS SqlSortOrderID, CONVERT(CHAR(100), SERVERPROPERTY('SqlSortOrderName')) AS SqlSortOrderName ORDER BY CONVERT(CHAR(100), SERVERPROPERTY('Servername')) END GO /****** Object: StoredProcedure [dbo].[utility_BASIC_ServiceCredentialBasicInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get service credential basic info -- ============================================= CREATE PROCEDURE [dbo].[utility_BASIC_ServiceCredentialBasicInfo] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED IF @@microsoftversion / power(2, 24) >= 9 BEGIN EXEC sp_configure 'show advanced options', 1 RECONFIGURE WITH OVERRIDE EXEC sp_configure 'xp_cmdshell', 1 RECONFIGURE WITH OVERRIDE END IF EXISTS ( SELECT Name FROM tempdb..sysobjects WHERE name LIKE '#MyTempTable%') DROP TABLE #MyTempTable CREATE TABLE #MyTempTable ( Big_String nvarchar(500) ) INSERT INTO #MyTempTable EXEC master..xp_cmdshell 'WMIC SERVICE GET Name,StartName | findstr /I SQL' -- show service accounts SELECT @@ServerName AS ServerName, RTRIM(Left(Big_String, CHARINDEX(' ', Big_String))) AS ServiceName, RTRIM(LTRIM(RTRIM(SUBSTRING(Big_String, CHARINDEX(' ', Big_String),LEN(Big_String))))) AS ServiceAccount FROM #MyTempTable IF @@microsoftversion / power(2, 24) >= 9 BEGIN EXEC sp_configure 'xp_cmdshell', 0 RECONFIGURE WITH OVERRIDE EXEC sp_configure 'show advanced options', 0 RECONFIGURE WITH OVERRIDE END END GO /****** Object: StoredProcedure [dbo].[utility_BLOCK_GetLockingInfoForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get locking information for all active processes, that is --processes that have a running request, is holding locks or have an --open transaction. Information about all locked objects are included, --as well the last command sent from the client and the currently --running statement. The procedure also displays the blocking chain --for blocked processes. -- ============================================= -- And here comes the procedure itself! CREATE PROCEDURE [dbo].[utility_BLOCK_GetLockingInfoForAllDatabase] @allprocesses bit = 0, @textmode bit = 0, @procdata char(1) = NULL, @debug bit = 0 AS SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED -- This table holds the information in sys.dm_tran_locks, aggregated -- on a number of items. Note that we do not include subthreads or -- requests in the aggregation. The IDENTITY column is there, because -- we don't want character data in the clustered index. DECLARE @locks TABLE ( database_id int NOT NULL, entity_id bigint NULL, session_id int NOT NULL, req_mode varchar(60) COLLATE Latin1_General_BIN2 NOT NULL, rsc_type varchar(60) COLLATE Latin1_General_BIN2 NOT NULL, rsc_subtype varchar(60) COLLATE Latin1_General_BIN2 NOT NULL, req_status varchar(60) COLLATE Latin1_General_BIN2 NOT NULL, req_owner_type varchar(60) COLLATE Latin1_General_BIN2 NOT NULL, rsc_description nvarchar(256) COLLATE Latin1_General_BIN2 NULL, min_entity_id bigint NULL, ismultipletemp bit NOT NULL DEFAULT 0, cnt int NOT NULL, activelock AS CASE WHEN rsc_type = 'DATABASE' AND req_status = 'GRANT' THEN convert(bit, 0) ELSE convert(bit, 1) END, ident int IDENTITY, rowno int NULL -- Set per session_id if @procdata is F. UNIQUE CLUSTERED (database_id, entity_id, session_id, ident) ) -- This table holds the translation of entity_id in @locks. This is a -- temp table since we access it from dynamic SQL. The type_desc is used -- for allocation units. The columns session_id, min_id and cnt are used -- when consolidating temp tables. CREATE TABLE #objects ( idtype char(4) NOT NULL CHECK (idtype IN ('OBJ', 'HOBT', 'AU', 'MISC')), database_id int NOT NULL, entity_id bigint NOT NULL, hobt_id bigint NULL, object_name nvarchar(550) COLLATE Latin1_General_BIN2 NULL, type_desc varchar(60) COLLATE Latin1_General_BIN2 NULL, session_id smallint NULL, min_id bigint NOT NULL, cnt int NOT NULL DEFAULT 1 PRIMARY KEY CLUSTERED (database_id, idtype, entity_id), UNIQUE NONCLUSTERED (database_id, entity_id, idtype), CHECK (NOT (session_id IS NOT NULL AND database_id <> 2)) ) -- This table captures sys.dm_os_waiting_tasks and later augment it with -- data about the block chain. A waiting task always has a always has a -- task address, but the blocker may be idle and without a task. -- All columns for the blocker are nullable, as we add extra rows for -- non-waiting blockers. DECLARE @dm_os_waiting_tasks TABLE (wait_session_id smallint NOT NULL, wait_task varbinary(8) NOT NULL, block_session_id smallint NULL, block_task varbinary(8) NULL, wait_type varchar(60) COLLATE Latin1_General_BIN2 NULL, wait_duration_ms bigint NULL, -- The level in the chain. Level 0 is the lead blocker. NULL for -- tasks that are waiting, but not blocking. block_level smallint NULL, -- The lead blocker for this block chain. lead_blocker_spid smallint NULL, -- Whether the block chain consists of the threads of the same spid only. blocksamespidonly bit NOT NULL DEFAULT 0, UNIQUE CLUSTERED (wait_session_id, wait_task, block_session_id, block_task), UNIQUE (block_session_id, block_task, wait_session_id, wait_task) ) -- This table holds information about transactions tied to a session. -- A session can have multiple transactions when there are multiple -- requests, but in that case we only save data about the oldest -- transaction. DECLARE @transactions TABLE ( session_id smallint NOT NULL, is_user_trans bit NOT NULL, trans_start datetime NOT NULL, trans_since decimal(10,3) NULL, trans_type int NOT NULL, trans_state int NOT NULL, dtc_state int NOT NULL, is_bound bit NOT NULL, PRIMARY KEY (session_id) ) -- This table holds information about all sessions and requests. DECLARE @procs TABLE ( session_id smallint NOT NULL, task_address varbinary(8) NOT NULL, exec_context_id int NOT NULL, request_id int NOT NULL, spidstr AS ltrim(str(session_id)) + CASE WHEN exec_context_id <> 0 OR request_id <> 0 THEN '/' + ltrim(str(exec_context_id)) + '/' + ltrim(str(request_id)) ELSE '' END, is_user_process bit NOT NULL, orig_login nvarchar(128) COLLATE Latin1_General_BIN2 NULL, current_login nvarchar(128) COLLATE Latin1_General_BIN2 NULL, session_state varchar(30) COLLATE Latin1_General_BIN2 NOT NULL, task_state varchar(60) COLLATE Latin1_General_BIN2 NULL, proc_dbid smallint NULL, request_dbid smallint NULL, host_name nvarchar(128) COLLATE Latin1_General_BIN2 NULL, host_process_id int NULL, endpoint_id int NOT NULL, program_name nvarchar(128) COLLATE Latin1_General_BIN2 NULL, request_command varchar(32) COLLATE Latin1_General_BIN2 NULL, trancount int NOT NULL, session_cpu int NOT NULL, request_cpu int NULL, session_physio bigint NOT NULL, request_physio bigint NULL, session_logreads bigint NOT NULL, request_logreads bigint NULL, session_tempdb bigint NULL, request_tempdb bigint NULL, isclr bit NOT NULL DEFAULT 0, nest_level int NULL, now datetime NOT NULL, login_time datetime NOT NULL, last_batch datetime NOT NULL, last_since decimal(10,3) NULL, curdbid smallint NULL, curobjid int NULL, current_stmt nvarchar(MAX) COLLATE Latin1_General_BIN2 NULL, sql_handle varbinary(64) NULL, plan_handle varbinary(64) NULL, stmt_start int NULL, stmt_end int NULL, current_plan xml NULL, rowno int NOT NULL, block_level tinyint NULL, block_session_id smallint NULL, block_exec_context_id int NULL, block_request_id int NULL, blockercnt int NULL, block_spidstr AS ltrim(str(block_session_id)) + CASE WHEN block_exec_context_id <> 0 OR block_request_id <> 0 THEN '/' + ltrim(str(block_exec_context_id)) + '/' + ltrim(str(block_request_id)) ELSE '' END + CASE WHEN blockercnt > 1 THEN ' (+' + ltrim(str(blockercnt - 1)) + ')' ELSE '' END, blocksamespidonly bit NOT NULL DEFAULT 0, waiter_no_blocker bit NOT NULL DEFAULT 0, wait_type varchar(60) COLLATE Latin1_General_BIN2 NULL, wait_time decimal(18,3) NULL, PRIMARY KEY (session_id, task_address)) -- Output from DBCC INPUTBUFFER. The IDENTITY column is there to make -- it possible to add the spid later. DECLARE @inputbuffer TABLE (eventtype nvarchar(30) NULL, params int NULL, inputbuffer nvarchar(4000) NULL, ident int IDENTITY UNIQUE, spid int NOT NULL DEFAULT 0 PRIMARY KEY) ------------------------------------------------------------------------ -- Local variables. ------------------------------------------------------------------------ DECLARE @now datetime, @ms int, @spid smallint, @rowc int, @lvl int, @dbname sysname, @dbidstr varchar(10), @objnameexpr nvarchar(MAX), @stmt nvarchar(MAX), @request_id int, @handle varbinary(64), @stmt_start int, @stmt_end int; ------------------------------------------------------------------------ -- Set up. ------------------------------------------------------------------------ -- All reads are dirty! The most important reason for this is tempdb.sys.objects. SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET NOCOUNT ON; SELECT @now = getdate(); -- Validate the @procdata parameter, and set default. IF @procdata IS NULL SELECT @procdata = CASE @textmode WHEN 1 THEN 'A' ELSE 'F' END IF @procdata NOT IN ('A', 'F') BEGIN RAISERROR('Invalid value for @procdata parameter. A and F are permitted', 16, 1) RETURN END -- Check that user has permissions enough. IF NOT EXISTS (SELECT * FROM sys.fn_my_permissions(NULL, NULL) WHERE permission_name = 'VIEW SERVER STATE') BEGIN RAISERROR('You need to have the permission VIEW SERVER STATE to run this procedure', 16, 1) RETURN END -- If there is a request for textdata output, jump to the end where we call -- ourselves non-texmode. (Ugly? Yes, having two procedures would be -- prettier, but it's easier only have to distribute one.) IF @textmode = 1 GOTO do_textmode ------------------------------------------------------------------------ -- First capture all locks. We aggregate by type, object etc to keep -- down the volume. ------------------------------------------------------------------------ IF @debug = 1 BEGIN RAISERROR ('Compiling lock information, time 0 ms.', 0, 1) WITH NOWAIT END; -- We force binary collation, to make the GROUP BY operation faster. WITH CTE AS ( SELECT request_session_id, req_mode = request_mode COLLATE Latin1_General_BIN2, rsc_type = resource_type COLLATE Latin1_General_BIN2, rsc_subtype = resource_subtype COLLATE Latin1_General_BIN2, req_status = request_status COLLATE Latin1_General_BIN2, req_owner_type = request_owner_type COLLATE Latin1_General_BIN2, rsc_description = CASE WHEN resource_type = 'APPLICATION' THEN nullif(resource_description COLLATE Latin1_General_BIN2, '') END, resource_database_id, resource_associated_entity_id FROM sys.dm_tran_locks) INSERT @locks (session_id, req_mode, rsc_type, rsc_subtype, req_status, req_owner_type, rsc_description, database_id, entity_id, min_entity_id, cnt) SELECT request_session_id, req_mode, rsc_type, rsc_subtype, req_status, req_owner_type, rsc_description, resource_database_id, resource_associated_entity_id, resource_associated_entity_id, COUNT(*) FROM CTE GROUP BY request_session_id, req_mode, rsc_type, rsc_subtype, req_status, req_owner_type, rsc_description, resource_database_id, resource_associated_entity_id ----------------------------------------------------------------------- -- Get the blocking chain. ----------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Determining blocking chain, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- First capture sys.dm_os_waiting_tasks, skipping non-spid tasks. The -- DISTINCT is needed, because there may be duplicates. (I've seen them.) INSERT @dm_os_waiting_tasks (wait_session_id, wait_task, block_session_id, block_task, wait_type, wait_duration_ms) SELECT DISTINCT owt.session_id, owt.waiting_task_address, owt.blocking_session_id, CASE WHEN owt.blocking_session_id IS NOT NULL THEN coalesce(owt.blocking_task_address, 0x) END, owt.wait_type, owt.wait_duration_ms FROM sys.dm_os_waiting_tasks owt WHERE owt.session_id IS NOT NULL; ----------------------------------------------------------------------- -- Get transaction. ----------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Determining active transactions, time %d ms.', 0, 1, @ms) WITH NOWAIT END ; WITH oldest_tran AS ( SELECT tst.session_id, tst.is_user_transaction, tat.transaction_begin_time, tat.transaction_type, tat.transaction_state, tat.dtc_state, tst.is_bound, rowno = row_number() OVER (PARTITION BY tst.session_id ORDER BY tat.transaction_begin_time ASC) FROM sys.dm_tran_session_transactions tst JOIN sys.dm_tran_active_transactions tat ON tst.transaction_id = tat.transaction_id ) INSERT @transactions(session_id, is_user_trans, trans_start, trans_since, trans_type, trans_state, dtc_state, is_bound) SELECT session_id, is_user_transaction, transaction_begin_time, CASE WHEN datediff(DAY, transaction_begin_time, @now) > 20 THEN NULL ELSE datediff(MS, transaction_begin_time, @now) / 1000.000 END, transaction_type, transaction_state, dtc_state, is_bound FROM oldest_tran WHERE rowno = 1 ------------------------------------------------------------------------ -- Then get the processes. We filter here for active processes once for all ------------------------------------------------------------------------ IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Collecting process information, time %d ms.', 0, 1, @ms) WITH NOWAIT END INSERT @procs(session_id, task_address, exec_context_id, request_id, is_user_process, current_login, orig_login, session_state, task_state, endpoint_id, proc_dbid, request_dbid, host_name, host_process_id, program_name, request_command, trancount, session_cpu, request_cpu, session_physio, request_physio, session_logreads, request_logreads, session_tempdb, request_tempdb, isclr, nest_level, now, login_time, last_batch, last_since, sql_handle, plan_handle, stmt_start, stmt_end, rowno) SELECT es.session_id, coalesce(ot.task_address, 0x), coalesce(ot.exec_context_id, 0), coalesce(er.request_id, 0), es.is_user_process, coalesce(nullif(es.login_name, ''), suser_sname(es.security_id)), coalesce(nullif(es.original_login_name, ''), suser_sname(es.original_security_id)), es.status, ot.task_state, es.endpoint_id, sp.dbid, er.database_id, es.host_name, es.host_process_id, es.program_name, er.command, coalesce(er.open_transaction_count, sp.open_tran), es.cpu_time, er.cpu_time, es.reads + es.writes, er.reads + er.writes, es.logical_reads, er.logical_reads, ssu.user_objects_alloc_page_count - ssu.user_objects_dealloc_page_count + ssu.internal_objects_alloc_page_count - ssu.internal_objects_dealloc_page_count, tsu.pages, coalesce(er.executing_managed_code, 0), er.nest_level, @now, es.login_time, es.last_request_start_time, CASE WHEN datediff(DAY, es.last_request_start_time, @now) > 20 THEN NULL ELSE datediff(MS, es.last_request_start_time, @now) / 1000.000 END, er.sql_handle, er.plan_handle, er.statement_start_offset, er.statement_end_offset, rowno = row_number() OVER (PARTITION BY es.session_id ORDER BY ot.exec_context_id, er.request_id) FROM sys.dm_exec_sessions es JOIN (SELECT spid, dbid = MIN(dbid), open_tran = MIN(open_tran) FROM sys.sysprocesses WHERE ecid = 0 GROUP BY spid) AS sp ON sp.spid = es.session_id LEFT JOIN sys.dm_os_tasks ot ON es.session_id = ot.session_id LEFT JOIN sys.dm_exec_requests er ON ot.task_address = er.task_address LEFT JOIN sys.dm_db_session_space_usage ssu ON es.session_id = ssu.session_id LEFT JOIN (SELECT session_id, request_id, SUM(user_objects_alloc_page_count - user_objects_dealloc_page_count + internal_objects_alloc_page_count - internal_objects_dealloc_page_count) AS pages FROM sys.dm_db_task_space_usage WHERE database_id = 2 GROUP BY session_id, request_id) AS tsu ON tsu.session_id = er.session_id AND tsu.request_id = er.request_id WHERE -- All processes requested @allprocesses > 0 -- All user sessions with a running request save ourselevs. OR ot.exec_context_id IS NOT NULL AND es.is_user_process = 1 AND es.session_id <> @@spid -- All sessions with an open transaction, even if they are idle. OR sp.open_tran > 0 AND es.session_id <> @@spid -- All sessions that have an interesting lock, save ourselves. OR EXISTS (SELECT * FROM @locks l WHERE l.session_id = es.session_id AND l.activelock = 1) AND es.session_id <> @@spid -- All sessions that is blocking someone. OR EXISTS (SELECT * FROM @dm_os_waiting_tasks owt WHERE owt.block_session_id = es.session_id) OR ssu.user_objects_alloc_page_count - ssu.user_objects_dealloc_page_count + ssu.internal_objects_alloc_page_count - ssu.internal_objects_dealloc_page_count > 1000 ------------------------------------------------------------------------ -- Get input buffers. Note that we can only find one per session, even -- a session has several requests. -- We skip this part if @@nestlevel is > 1, as presumably we are calling -- ourselves recursively from INSERT EXEC, and we may no not do another -- level of INSERT-EXEC. ------------------------------------------------------------------------ IF @@nestlevel = 1 BEGIN IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Getting input buffers, time %d ms.', 0, 1, @ms) WITH NOWAIT END DECLARE C1 CURSOR FAST_FORWARD LOCAL FOR SELECT DISTINCT session_id FROM @procs WHERE is_user_process = 1 OPEN C1 WHILE 1 = 1 BEGIN FETCH C1 INTO @spid IF @@fetch_status <> 0 BREAK BEGIN TRY INSERT @inputbuffer(eventtype, params, inputbuffer) EXEC sp_executesql N'DBCC INPUTBUFFER (@spid) WITH NO_INFOMSGS', N'@spid int', @spid UPDATE @inputbuffer SET spid = @spid WHERE ident = scope_identity() END TRY BEGIN CATCH INSERT @inputbuffer(inputbuffer, spid) VALUES('Error getting inputbuffer: ' + error_message(), @spid) END CATCH END DEALLOCATE C1 END ----------------------------------------------------------------------- -- Compute the blocking chain. ----------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Computing blocking chain, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- Mark blockers that are waiting, that is waiting for something else -- than another spid. UPDATE @dm_os_waiting_tasks SET block_level = 0, lead_blocker_spid = a.wait_session_id FROM @dm_os_waiting_tasks a WHERE a.block_session_id IS NULL AND EXISTS (SELECT * FROM @dm_os_waiting_tasks b WHERE a.wait_session_id = b.block_session_id AND a.wait_task = b.block_task) SELECT @rowc = @@rowcount -- Add an extra row for blockers that are not waiting at all. INSERT @dm_os_waiting_tasks (wait_session_id, wait_task, block_level, lead_blocker_spid) SELECT DISTINCT a.block_session_id, coalesce(a.block_task, 0x), 0, a.block_session_id FROM @dm_os_waiting_tasks a WHERE NOT EXISTS (SELECT * FROM @dm_os_waiting_tasks b WHERE a.block_session_id = b.wait_session_id AND a.block_task = b.wait_task) AND a.block_session_id IS NOT NULL; SELECT @rowc = @rowc + @@rowcount, @lvl = 0 -- Then iterate as long as we find blocked processes. You may think -- that a recursive CTE would be great here, but we want to exclude -- rows that has already been marked. This is difficult to do with a CTE. WHILE @rowc > 0 BEGIN UPDATE a SET block_level = b.block_level + 1, lead_blocker_spid = b.lead_blocker_spid FROM @dm_os_waiting_tasks a JOIN @dm_os_waiting_tasks b ON a.block_session_id = b.wait_session_id AND a.block_task = b.wait_task WHERE b.block_level = @lvl AND a.block_level IS NULL SELECT @rowc = @@rowcount, @lvl = @lvl + 1 END -- Next to find are processes that are blocked, but no one is waiting for. -- They are directly or indirectly blocked by a deadlock. They get a -- negative level initially. We clean this up later. UPDATE @dm_os_waiting_tasks SET block_level = -1 FROM @dm_os_waiting_tasks a WHERE a.block_level IS NULL AND a.block_session_id IS NOT NULL AND NOT EXISTS (SELECT * FROM @dm_os_waiting_tasks b WHERE b.block_session_id = a.wait_session_id AND b.block_task = a.wait_task) SELECT @rowc = @@rowcount, @lvl = -2 -- Then unwind these chains in the opposite direction to before. WHILE @rowc > 0 BEGIN UPDATE @dm_os_waiting_tasks SET block_level = @lvl FROM @dm_os_waiting_tasks a WHERE a.block_level IS NULL AND a.block_session_id IS NOT NULL AND NOT EXISTS (SELECT * FROM @dm_os_waiting_tasks b WHERE b.block_session_id = a.wait_session_id AND b.block_task = a.wait_task AND b.block_level IS NULL) SELECT @rowc = @@rowcount, @lvl = @lvl - 1 END -- Determine which blocking tasks that only block tasks within the same -- spid. UPDATE @dm_os_waiting_tasks SET blocksamespidonly = 1 FROM @dm_os_waiting_tasks a WHERE a.block_level IS NOT NULL AND a.wait_session_id = a.lead_blocker_spid AND NOT EXISTS (SELECT * FROM @dm_os_waiting_tasks b WHERE a.wait_session_id = b.lead_blocker_spid AND a.wait_session_id <> b.wait_session_id) ----------------------------------------------------------------------- -- Add block-chain and wait information to @procs. If a blockee has more -- than one blocker, we pick one. ----------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Adding blocking chain to @procs, time %d ms.', 0, 1, @ms) WITH NOWAIT END ; WITH block_chain AS ( SELECT wait_session_id, wait_task, block_session_id, block_task, block_level = CASE WHEN block_level >= 0 THEN block_level ELSE block_level - @lvl - 1 END, wait_duration_ms, wait_type, blocksamespidonly, cnt = COUNT(*) OVER (PARTITION BY wait_task), rowno = row_number() OVER (PARTITION BY wait_task ORDER BY block_level, block_task) FROM @dm_os_waiting_tasks ) UPDATE p SET block_level = bc.block_level, block_session_id = bc.block_session_id, block_exec_context_id = coalesce(p2.exec_context_id, -1), block_request_id = coalesce(p2.request_id, -1), blockercnt = bc.cnt, blocksamespidonly = bc.blocksamespidonly, wait_time = convert(decimal(18, 3), bc.wait_duration_ms) / 1000, wait_type = bc.wait_type FROM @procs p JOIN block_chain bc ON p.session_id = bc.wait_session_id AND p.task_address = bc.wait_task AND bc.rowno = 1 LEFT JOIN @procs p2 ON bc.block_session_id = p2.session_id AND bc.block_task = p2.task_address -------------------------------------------------------------------- -- Delete "uninteresting" locks from @locks for processes not in @procs. -------------------------------------------------------------------- IF @allprocesses = 0 BEGIN IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Deleting uninteresting locks, time %d ms.', 0, 1, @ms) WITH NOWAIT END DELETE @locks FROM @locks l WHERE (activelock = 0 OR session_id = @@spid) AND NOT EXISTS (SELECT * FROM @procs p WHERE p.session_id = l.session_id) END ---------------------------------------------------------------------- -- Get the query text. This is not done in the main query, as we could -- be blocked if someone is creating an SP and executes it in a -- transaction. ---------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Retrieving current statement, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- Set lock timeout to avoid being blocked. SET LOCK_TIMEOUT 5 -- First try to get all query plans in one go. BEGIN TRY UPDATE @procs SET curdbid = est.dbid, curobjid = est.objectid, current_stmt = CASE WHEN est.encrypted = 1 THEN '-- ENCRYPTED, pos ' + ltrim(str((p.stmt_start + 2)/2)) + ' - ' + ltrim(str((p.stmt_end + 2)/2)) WHEN p.stmt_start >= 0 THEN substring(est.text, (p.stmt_start + 2)/2, CASE p.stmt_end WHEN -1 THEN datalength(est.text) ELSE (p.stmt_end - p.stmt_start + 2) / 2 END) END FROM @procs p CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) est END TRY BEGIN CATCH -- If this fails, try to get the texts one by one. DECLARE text_cur CURSOR STATIC LOCAL FOR SELECT DISTINCT session_id, request_id, sql_handle, stmt_start, stmt_end FROM @procs WHERE sql_handle IS NOT NULL OPEN text_cur WHILE 1 = 1 BEGIN FETCH text_cur INTO @spid, @request_id, @handle, @stmt_start, @stmt_end IF @@fetch_status <> 0 BREAK BEGIN TRY UPDATE @procs SET curdbid = est.dbid, curobjid = est.objectid, current_stmt = CASE WHEN est.encrypted = 1 THEN '-- ENCRYPTED, pos ' + ltrim(str((p.stmt_start + 2)/2)) + ' - ' + ltrim(str((p.stmt_end + 2)/2)) WHEN p.stmt_start >= 0 THEN substring(est.text, (p.stmt_start + 2)/2, CASE p.stmt_end WHEN -1 THEN datalength(est.text) ELSE (p.stmt_end - p.stmt_start + 2) / 2 END) END FROM @procs p CROSS APPLY sys.dm_exec_sql_text(p.sql_handle) est WHERE p.session_id = @spid AND p.request_id = @request_id END TRY BEGIN CATCH UPDATE @procs SET current_stmt = 'ERROR: *** ' + error_message() + ' ***' WHERE session_id = @spid AND request_id = @request_id END CATCH END DEALLOCATE text_cur END CATCH SET LOCK_TIMEOUT 0 ----------------------------------------------------------------------- -- Get object names from ids in @procs and @locks. You may think that -- we could use object_name and its second database parameter, but -- object_name takes out a Sch-S lock (even with READ UNCOMMITTED) and -- gets blocked if a object (read temp table) has been created in a transaction. ----------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Getting object names, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- First get all entity ids into the temp table. And yes, do save them in -- three columns. We translate the resource types to our own type, depending -- on names are to be looked up. The session_id is only of interest in -- tempdb and only for temp tables. We use MIN, since is the same data -- appears for the same session_id, it cannot be a temp table. INSERT #objects (idtype, database_id, entity_id, hobt_id, min_id, session_id) SELECT idtype, database_id, entity_id, entity_id, entity_id, MIN(session_id) FROM (SELECT CASE WHEN rsc_type = 'OBJECT' THEN 'OBJ' WHEN rsc_type IN ('PAGE', 'KEY', 'RID', 'HOBT') THEN 'HOBT' WHEN rsc_type = 'ALLOCATION_UNIT' THEN 'AU' END AS idtype, database_id, entity_id, CASE database_id WHEN 2 THEN session_id END AS session_id FROM @locks) AS l WHERE idtype IS NOT NULL GROUP BY idtype, database_id, entity_id UNION SELECT DISTINCT 'OBJ', curdbid, curobjid, curobjid, curobjid, NULL FROM @procs WHERE curdbid IS NOT NULL AND curobjid IS NOT NULL -- If the user does not have CONTROL SERVER, he may not be able to access all -- databases. In this case, we save this to the table directly, rather than -- handling it the error handler below (because else it destroys textmode). IF NOT EXISTS (SELECT * FROM sys.fn_my_permissions(NULL, NULL) WHERE permission_name = 'CONTROL SERVER') BEGIN UPDATE #objects SET object_name = 'You do not have permissions to access the database ' + quotename(db_name(database_id)) + '.' WHERE has_dbaccess(db_name(database_id)) = 0 END DECLARE C2 CURSOR STATIC LOCAL FOR SELECT DISTINCT str(database_id), quotename(db_name(database_id)) FROM #objects WHERE idtype IN ('OBJ', 'HOBT', 'AU') AND object_name IS NULL OPTION (KEEPFIXED PLAN) OPEN C2 WHILE 1 = 1 BEGIN FETCH C2 INTO @dbidstr, @dbname IF @@fetch_status <> 0 BREAK -- This expression is used to for the object name. It looks differently -- in tempdb where we drop the unique parts of temp-tables. SELECT @objnameexpr = CASE @dbname WHEN '[tempdb]' THEN 'CASE WHEN len(o.name) = 9 AND o.name LIKE "#" + replicate("[0-9A-F]", 8) THEN "#(tblvar or dropped temp table)" WHEN len(o.name) = 128 AND o.name LIKE "#[^#]%" THEN substring(o.name, 1, charindex("_____", o.name) - 1) ELSE db_name(@dbidstr) + "." + coalesce(s.name + "." + o.name, "<" + ltrim(str(ob.entity_id)) + ">") END' ELSE 'db_name(@dbidstr) + "." + coalesce(s.name + "." + o.name, "<" + ltrim(str(ob.entity_id)) + ">")' END -- First handle allocation units. They bring us a hobt_id, or we go -- directly to the object when the container is a partition_id. We -- always get the type_desc. To make the dynamic SQL easier to read, -- we use some placeholders. SELECT @stmt = ' UPDATE #objects SET type_desc = au.type_desc, hobt_id = CASE WHEN au.type IN (1, 3) THEN au.container_id END, idtype = CASE WHEN au.type IN (1, 3) THEN "HOBT" ELSE "AU" END, object_name = CASE WHEN au.type = 2 THEN ' + @objnameexpr + ' + CASE WHEN p.index_id <= 1 THEN "" ELSE "." + i.name END + CASE WHEN p.partition_number > 1 THEN "(" + ltrim(str(p.partition_number)) + ")" ELSE "" END WHEN au.type = 0 THEN db_name(@dbidstr) + " (dropped table et al)" END FROM #objects ob JOIN @dbname.sys.allocation_units au ON ob.entity_id = au.allocation_unit_id -- We should only go all the way from sys.partitions, for type = 3. LEFT JOIN (@dbname.sys.partitions p JOIN @dbname.sys.objects o ON p.object_id = o.object_id JOIN @dbname.sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id JOIN @dbname.sys.schemas s ON o.schema_id = s.schema_id) ON au.container_id = p.partition_id AND au.type = 2 WHERE ob.database_id = @dbidstr AND ob.idtype = "AU" OPTION (KEEPFIXED PLAN); ' -- Now we can translate all hobt_id, including those we got from the -- allocation units. SELECT @stmt = @stmt + ' UPDATE #objects SET object_name = ' + @objnameexpr + ' + CASE WHEN p.index_id <= 1 THEN "" ELSE "." + i.name END + CASE WHEN p.partition_number > 1 THEN "(" + ltrim(str(p.partition_number)) + ")" ELSE "" END + coalesce(" (" + ob.type_desc + ")", "") FROM #objects ob JOIN @dbname.sys.partitions p ON ob.hobt_id = p.hobt_id JOIN @dbname.sys.objects o ON p.object_id = o.object_id JOIN @dbname.sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id JOIN @dbname.sys.schemas s ON o.schema_id = s.schema_id WHERE ob.database_id = @dbidstr AND ob.idtype = "HOBT" OPTION (KEEPFIXED PLAN) ' -- And now object ids, idtype = OBJ. SELECT @stmt = @stmt + ' UPDATE #objects SET object_name = ' + @objnameexpr + ' FROM #objects ob LEFT JOIN (@dbname.sys.objects o JOIN @dbname.sys.schemas s ON o.schema_id = s.schema_id) ON convert(int, ob.entity_id) = o.object_id WHERE ob.database_id = @dbidstr AND ob.idtype = "OBJ" OPTION (KEEPFIXED PLAN) ' -- When running beta_lockinfo with only VIEW SERVER STATE, without being -- sysadmin, reading from the system tables will block on SQL 2005 and -- SQL 2008. Address this. SELECT @stmt = ' BEGIN TRY SET LOCK_TIMEOUT 5 ' + @stmt + ' END TRY BEGIN CATCH UPDATE #objects SET object_name = "Error getting object name: " + error_message() WHERE database_id = @dbidstr AND object_name IS NULL END CATCH ' -- Fix the placeholders. SELECT @stmt = replace(replace(replace(@stmt, '"', ''''), '@dbname', @dbname), '@dbidstr', @dbidstr) -- And run the beast. -- PRINT @stmt EXEC (@stmt) END DEALLOCATE C2 ------------------------------------------------------------------- -- Consolidate temp tables, so that if a procedure has a lock on -- several temp tables with the same name, it is only listed once. ------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Consolidating temp tables, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- Count the temp tables, and find the lowest id in each group. ; WITH mintemp AS ( SELECT object_name, session_id, idtype, MIN(entity_id) AS min_id, COUNT(*) AS cnt FROM #objects WHERE database_id = 2 AND object_name LIKE '#[^#]%' GROUP BY object_name, session_id, idtype HAVING COUNT(*) > 1 ) UPDATE #objects SET min_id = m.min_id, cnt = m.cnt, object_name = m.object_name + ' (x' + ltrim(str(m.cnt)) + ')' FROM #objects o JOIN mintemp m ON m.object_name = o.object_name AND m.idtype = o.idtype AND m.session_id = o.session_id WHERE o.database_id = 2 OPTION (KEEPFIXED PLAN) SELECT @rowc = @@rowcount IF @rowc > 0 BEGIN UPDATE @locks SET min_entity_id = ob.min_id, ismultipletemp = 1 FROM @locks l JOIN #objects ob ON l.database_id = ob.database_id AND l.entity_id = ob.entity_id AND l.session_id = ob.session_id WHERE l.database_id = 2 AND ob.database_id = 2 AND ob.cnt > 1 OPTION (KEEPFIXED PLAN) INSERT @locks (session_id, req_mode, rsc_type, rsc_subtype, req_status, req_owner_type, database_id, entity_id, cnt) SELECT session_id, req_mode, rsc_type, rsc_subtype, req_status, req_owner_type, 2, min_entity_id, SUM(cnt) FROM @locks WHERE database_id = 2 AND ismultipletemp = 1 GROUP BY session_id, req_mode, rsc_type, rsc_subtype, req_status, req_owner_type, min_entity_id END -------------------------------------------------------------------- -- Get query plans. The difficult part is that the convert to xml may -- fail if the plan is too deep. Therefore we catch this error, and -- resort to a cursor in this case. Since query plans are not included -- in text mode, we skip if @nestlevel is > 1. -------------------------------------------------------------------- IF @@nestlevel = 1 BEGIN IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Retrieving query plans, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- Adam says that getting the query plans can time out too... SET LOCK_TIMEOUT 5 BEGIN TRY UPDATE @procs SET current_plan = convert(xml, etqp.query_plan) FROM @procs p OUTER APPLY sys.dm_exec_text_query_plan( p.plan_handle, p.stmt_start, p.stmt_end) etqp WHERE p.plan_handle IS NOT NULL END TRY BEGIN CATCH DECLARE plan_cur CURSOR STATIC LOCAL FOR SELECT DISTINCT session_id, request_id, plan_handle, stmt_start, stmt_end FROM @procs WHERE plan_handle IS NOT NULL OPEN plan_cur WHILE 1 = 1 BEGIN FETCH plan_cur INTO @spid, @request_id, @handle, @stmt_start, @stmt_end IF @@fetch_status <> 0 BREAK BEGIN TRY UPDATE @procs SET current_plan = (SELECT convert(xml, etqp.query_plan) FROM sys.dm_exec_text_query_plan( @handle, @stmt_start, @stmt_end) etqp) FROM @procs p WHERE p.session_id = @spid AND p.request_id = @request_id END TRY BEGIN CATCH UPDATE @procs SET current_plan = (SELECT 'Could not get query plan' AS [@alert], error_number() AS [@errno], error_severity() AS [@level], error_message() AS [@errmsg] FOR XML PATH('ERROR')) WHERE session_id = @spid AND request_id = @request_id END CATCH END DEALLOCATE plan_cur END CATCH SET LOCK_TIMEOUT 0 -- There is a bug in dm_exec_text_query_plan which causes the attribute -- StatementText to include the full text of the batch up to current -- statement. This causes bloat in SSMS. Whence we fix the attribute. ; WITH XMLNAMESPACES( 'http://schemas.microsoft.com/sqlserver/2004/07/showplan' AS SP) UPDATE @procs SET current_plan.modify(' replace value of ( /SP:ShowPlanXML/SP:BatchSequence/SP:Batch/ SP:Statements/SP:StmtSimple/@StatementText)[1] with substring((/SP:ShowPlanXML/SP:BatchSequence/SP:Batch/ SP:Statements/SP:StmtSimple/@StatementText)[1], (sql:column("stmt_start") + 2) div 2) ') WHERE current_plan IS NOT NULL AND stmt_start IS NOT NULL END -------------------------------------------------------------------- -- If user has selected to see process data only on the first row, -- we should number the rows in @locks. -------------------------------------------------------------------- IF @procdata = 'F' BEGIN IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Determining first row, time %d ms.', 0, 1, @ms) WITH NOWAIT END ; WITH locks_rowno AS ( SELECT rowno, new_rowno = row_number() OVER(PARTITION BY l.session_id ORDER BY CASE l.req_status WHEN 'GRANT' THEN 'ZZZZ' ELSE l.req_status END, o.object_name, l.rsc_type, l.rsc_description) FROM @locks l LEFT JOIN #objects o ON l.database_id = o.database_id AND l.entity_id = o.entity_id) UPDATE locks_rowno SET rowno = new_rowno OPTION (KEEPFIXED PLAN) END --------------------------------------------------------------------- -- Before we can join in the locks, we need to make sure that all -- processes with a running request has a row with exec_context_id = -- request_id = 0. (Those without already has such a row.) --------------------------------------------------------------------- IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Supplementing @procs, time %d ms.', 0, 1, @ms) WITH NOWAIT END INSERT @procs(session_id, task_address, exec_context_id, request_id, is_user_process, orig_login, current_login, session_state, endpoint_id, trancount, proc_dbid, host_name, host_process_id, program_name, session_cpu, session_physio, session_logreads, now, login_time, last_batch, last_since, rowno) SELECT session_id, 0x, 0, 0, is_user_process, orig_login, current_login, session_state, endpoint_id, 0, proc_dbid, host_name, host_process_id, program_name, session_cpu, session_physio, session_logreads, now, login_time, last_batch, last_since, 0 FROM @procs a WHERE a.rowno = 1 AND NOT EXISTS (SELECT * FROM @procs b WHERE b.session_id = a.session_id AND b.exec_context_id = 0 AND b.request_id = 0) -- A process may be waiting for a lock according sys.dm_os_tran_locks, -- but it was not in sys.dm_os_waiting_tasks. Let's mark this up. UPDATE @procs SET waiter_no_blocker = 1 FROM @procs p WHERE EXISTS (SELECT * FROM @locks l WHERE l.req_status = 'WAIT' AND l.session_id = p.session_id AND NOT EXISTS (SELECT * FROM @procs p2 WHERE p.session_id = l.session_id)) ------------------------------------------------------------------------ -- For Plain results we are ready to return now. ------------------------------------------------------------------------ IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Returning result set, time %d ms.', 0, 1, @ms) WITH NOWAIT END IF @textmode = 0 BEGIN -- Note that the query is a full join, since @locks and @procs may not -- be in sync. Processes may have gone away, or be active without any -- locks. As for the transactions, we team up with the processes. SELECT spid = coalesce(p.spidstr, ltrim(str(l.session_id))), command = CASE WHEN coalesce(p.exec_context_id, 0) = 0 AND coalesce(l.rowno, 1) = 1 THEN p.request_command ELSE '' END, login = CASE WHEN coalesce(p.exec_context_id, 0) = 0 AND coalesce(l.rowno, 1) = 1 THEN CASE WHEN p.is_user_process = 0 THEN 'SYSTEM PROCESS' ELSE p.orig_login + CASE WHEN p.current_login <> p.orig_login OR p.orig_login IS NULL THEN ' (' + p.current_login + ')' ELSE '' END END ELSE '' END, host = CASE WHEN coalesce(p.exec_context_id, 0)= 0 AND coalesce(l.rowno, 1) = 1 THEN p.host_name ELSE '' END, hostprc = CASE WHEN coalesce(p.exec_context_id, 0) = 0 AND coalesce(l.rowno, 1) = 1 THEN ltrim(str(p.host_process_id)) ELSE '' END, endpoint = CASE WHEN coalesce(p.exec_context_id, 0) = 0 AND coalesce(l.rowno, 1) = 1 THEN e.name ELSE '' END, appl = CASE WHEN coalesce(p.exec_context_id, 0) = 0 AND coalesce(l.rowno, 1) = 1 THEN p.program_name ELSE '' END, dbname = CASE WHEN coalesce(l.rowno, 1) = 1 AND coalesce(p.exec_context_id, 0) = 0 THEN coalesce(db_name(p.request_dbid), db_name(p.proc_dbid)) ELSE '' END, prcstatus = CASE WHEN coalesce(l.rowno, 1) = 1 THEN coalesce(p.task_state, p.session_state) ELSE '' END, spid_ = p.spidstr, opntrn = CASE WHEN p.exec_context_id = 0 THEN coalesce(ltrim(str(nullif(p.trancount, 0))), '') ELSE '' END, trninfo = CASE WHEN coalesce(l.rowno, 1) = 1 AND p.exec_context_id = 0 AND t.is_user_trans IS NOT NULL THEN CASE t.is_user_trans WHEN 1 THEN 'U' ELSE 'S' END + '-' + CASE t.trans_type WHEN 1 THEN 'RW' WHEN 2 THEN 'R' WHEN 3 THEN 'SYS' WHEN 4 THEN 'DIST' ELSE ltrim(str(t.trans_type)) END + '-' + ltrim(str(t.trans_state)) + CASE t.dtc_state WHEN 0 THEN '' ELSE '-' END + CASE t.dtc_state WHEN 0 THEN '' WHEN 1 THEN 'DTC:ACTIVE' WHEN 2 THEN 'DTC:PREPARED' WHEN 3 THEN 'DTC:COMMITED' WHEN 4 THEN 'DTC:ABORTED' WHEN 5 THEN 'DTC:RECOVERED' ELSE 'DTC:' + ltrim(str(t.dtc_state)) END + CASE t.is_bound WHEN 0 THEN '' WHEN 1 THEN '-BND' END ELSE '' END, blklvl = CASE WHEN p.block_level IS NOT NULL THEN CASE p.blocksamespidonly WHEN 1 THEN '(' ELSE '' END + CASE WHEN p.block_level = 0 THEN '!!' ELSE ltrim(str(p.block_level)) END + CASE p.blocksamespidonly WHEN 1 THEN ')' ELSE '' END -- If the process is blocked, but we do not -- have a block level, the process is in a -- dead lock. WHEN p.block_session_id IS NOT NULL THEN 'DD' WHEN p.waiter_no_blocker = 1 THEN '??' ELSE '' END, blkby = coalesce(p.block_spidstr, ''), cnt = CASE WHEN p.exec_context_id = 0 AND p.request_id = 0 THEN coalesce(ltrim(str(l.cnt)), '0') ELSE '' END, object = CASE l.rsc_type WHEN 'APPLICATION' THEN coalesce(db_name(l.database_id) + '|', '') + l.rsc_description ELSE coalesce(o2.object_name, db_name(l.database_id), '') END, rsctype = coalesce(l.rsc_type, ''), locktype = coalesce(l.req_mode, ''), lstatus = CASE l.req_status WHEN 'GRANT' THEN lower(l.req_status) ELSE coalesce(l.req_status, '') END, ownertype = CASE l.req_owner_type WHEN 'SHARED_TRANSACTION_WORKSPACE' THEN 'STW' ELSE coalesce(l.req_owner_type, '') END, rscsubtype = coalesce(l.rsc_subtype, ''), waittime = CASE WHEN coalesce(l.rowno, 1) = 1 THEN coalesce(ltrim(str(p.wait_time, 18, 3)), '') ELSE '' END, waittype = CASE WHEN coalesce(l.rowno, 1) = 1 THEN coalesce(p.wait_type, '') ELSE '' END, spid__ = p.spidstr, cpu = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN coalesce(ltrim(str(p.session_cpu)), '') + CASE WHEN p.request_cpu IS NOT NULL THEN ' (' + ltrim(str(p.request_cpu)) + ')' ELSE '' END ELSE '' END, physio = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN coalesce(ltrim(str(p.session_physio, 18)), '') + CASE WHEN p.request_physio IS NOT NULL THEN ' (' + ltrim(str(p.request_physio)) + ')' ELSE '' END ELSE '' END, logreads = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN coalesce(ltrim(str(p.session_logreads, 18)), '') + CASE WHEN p.request_logreads IS NOT NULL THEN ' (' + ltrim(str(p.request_logreads)) + ')' ELSE '' END ELSE '' END, tempdb = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN coalesce(ltrim(str(p.session_tempdb, 18)), '') + CASE WHEN p.request_tempdb IS NOT NULL THEN ' (' + ltrim(str(p.request_tempdb)) + ')' ELSE '' END ELSE '' END, now = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN convert(char(12), p.now, 114) ELSE '' END, login_time = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN CASE datediff(DAY, p.login_time, @now) WHEN 0 THEN convert(varchar(8), p.login_time, 8) ELSE convert(char(7), p.login_time, 12) + convert(varchar(8), p.login_time, 8) END ELSE '' END, last_batch = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN CASE datediff(DAY, p.last_batch, @now) WHEN 0 THEN convert(varchar(8), p.last_batch, 8) ELSE convert(char(7), p.last_batch, 12) + convert(varchar(8), p.last_batch, 8) END ELSE '' END, trn_start = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 AND t.trans_start IS NOT NULL THEN CASE datediff(DAY, t.trans_start, @now) WHEN 0 THEN convert(varchar(8), t.trans_start, 8) ELSE convert(char(7), t.trans_start, 12) + convert(varchar(8), t.trans_start, 8) END ELSE '' END, last_since = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN str(p.last_since, 11, 3) ELSE '' END, trn_since = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 AND t.trans_since IS NOT NULL THEN str(t.trans_since, 11, 3) ELSE '' END, clr = CASE WHEN p.exec_context_id = 0 AND p.isclr = 1 THEN 'CLR' ELSE '' END, nstlvl = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN coalesce(ltrim(str(p.nest_level)), '') ELSE '' END, spid___ = p.spidstr, inputbuffer = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN coalesce(i.inputbuffer, '') ELSE '' END, current_sp = coalesce(o1.object_name, ''), curstmt = CASE WHEN coalesce(l.rowno, 1) = 1 THEN coalesce(p.current_stmt, '') ELSE coalesce(substring( p.current_stmt, 1, 50), '') END, current_plan = CASE WHEN p.exec_context_id = 0 AND coalesce(l.rowno, 1) = 1 THEN p.current_plan END FROM @procs p LEFT JOIN #objects o1 ON p.curdbid = o1.database_id AND p.curobjid = o1.entity_id LEFT JOIN @inputbuffer i ON p.session_id = i.spid AND p.exec_context_id = 0 LEFT JOIN sys.endpoints e ON p.endpoint_id = e.endpoint_id LEFT JOIN @transactions t ON t.session_id = p.session_id FULL JOIN ((SELECT * FROM @locks WHERE ismultipletemp = 0) AS l LEFT JOIN #objects o2 ON l.database_id = o2.database_id AND l.entity_id = o2.entity_id) ON p.session_id = l.session_id AND p.exec_context_id = 0 AND p.request_id = 0 ORDER BY coalesce(p.session_id, l.session_id), p.exec_context_id, coalesce(nullif(p.request_id, 0), 99999999), l.rowno, lstatus, coalesce(o2.object_name, db_name(l.database_id)), l.rsc_type, l.rsc_description OPTION (KEEPFIXED PLAN) END ELSE BEGIN do_textmode: ------------------------------------------------------------------------ -- For textmode result, we run ourselves in gridmode, receiving the -- result into a temp table. ------------------------------------------------------------------------ CREATE TABLE #textmode( ident int IDENTITY, spid varchar(30) COLLATE Latin1_General_BIN2 NOT NULL, command varchar(32) COLLATE Latin1_General_BIN2 NULL, login sysname COLLATE Latin1_General_BIN2 NULL, host nvarchar(128) COLLATE Latin1_General_BIN2 NULL, hostprc varchar(10) COLLATE Latin1_General_BIN2 NULL, endpoint sysname COLLATE Latin1_General_BIN2 NULL, appl nvarchar(128) COLLATE Latin1_General_BIN2 NULL, dbname sysname COLLATE Latin1_General_BIN2 NULL, prcstatus varchar(60) COLLATE Latin1_General_BIN2 NULL, spid_ varchar(30) COLLATE Latin1_General_BIN2 NULL, opntrn varchar(10) COLLATE Latin1_General_BIN2 NULL, trninfo varchar(30) COLLATE Latin1_General_BIN2 NULL, blklvl char(3) COLLATE Latin1_General_BIN2 NULL, blkby varchar(30) COLLATE Latin1_General_BIN2 NULL, cnt varchar(10) COLLATE Latin1_General_BIN2 NULL, object nvarchar(520) COLLATE Latin1_General_BIN2 NULL, rsctype varchar(60) COLLATE Latin1_General_BIN2 NULL, locktype varchar(60) COLLATE Latin1_General_BIN2 NULL, lstatus varchar(60) COLLATE Latin1_General_BIN2 NULL, ownertype varchar(60) COLLATE Latin1_General_BIN2 NULL, rscsubtype varchar(60) COLLATE Latin1_General_BIN2 NULL, waittime varchar(16) COLLATE Latin1_General_BIN2 NULL, waittype varchar(60) COLLATE Latin1_General_BIN2 NULL, spid__ varchar(30) COLLATE Latin1_General_BIN2 NULL, cpu varchar(30) COLLATE Latin1_General_BIN2 NULL, physio varchar(50) COLLATE Latin1_General_BIN2 NULL, logreads varchar(50) COLLATE Latin1_General_BIN2 NULL, tempdb varchar(50) COLLATE Latin1_General_BIN2 NULL, now char(12) COLLATE Latin1_General_BIN2 NULL, login_time varchar(16) COLLATE Latin1_General_BIN2 NULL, last_batch varchar(16) COLLATE Latin1_General_BIN2 NULL, trn_start varchar(16) COLLATE Latin1_General_BIN2 NULL, last_since varchar(11) COLLATE Latin1_General_BIN2 NULL, trn_since varchar(11) COLLATE Latin1_General_BIN2 NULL, clr char(3) COLLATE Latin1_General_BIN2 NULL, nstlvl char(3) COLLATE Latin1_General_BIN2 NULL, spid___ varchar(30) COLLATE Latin1_General_BIN2 NULL, inputbuffer nvarchar(4000) COLLATE Latin1_General_BIN2 NULL, current_sp nvarchar(400) COLLATE Latin1_General_BIN2 NULL, curstmt nvarchar(MAX) COLLATE Latin1_General_BIN2 NULL, queryplan xml NULL, last bit NOT NULL DEFAULT 0) -- Do the recursive call. INSERT #textmode (spid, command, login, host, hostprc, endpoint, appl, dbname, prcstatus, spid_, opntrn, trninfo, blklvl, blkby, cnt, object, rsctype, locktype, lstatus, ownertype, rscsubtype, waittime, waittype, spid__, cpu, physio, logreads, tempdb, now, login_time, last_batch, trn_start, last_since, trn_since, clr, nstlvl, spid___, inputbuffer, current_sp, curstmt, queryplan) EXEC beta_lockinfo @allprocesses = @allprocesses, @textmode = 0, @procdata = @procdata, @debug = @debug -- inputbuffer is always NULL, as the recursive call skips that part. -- We need to do that now. IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Getting input buffers, time %d ms.', 0, 1, @ms) WITH NOWAIT END DECLARE C3 CURSOR FAST_FORWARD LOCAL FOR SELECT DISTINCT spid FROM #textmode WHERE login <> 'SYSTEM PROCESS' AND spid NOT LIKE '%/%' OPEN C3 WHILE 1 = 1 BEGIN FETCH C3 INTO @spid IF @@fetch_status <> 0 BREAK BEGIN TRY INSERT @inputbuffer(eventtype, params, inputbuffer) EXEC sp_executesql N'DBCC INPUTBUFFER (@spid) WITH NO_INFOMSGS', N'@spid int', @spid UPDATE @inputbuffer SET spid = @spid WHERE ident = scope_identity() END TRY BEGIN CATCH INSERT @inputbuffer(inputbuffer, spid) VALUES('Error getting inputbuffer: ' + error_message(), @spid) END CATCH END DEALLOCATE C3 -- Copy to the temp table and remove line breaks while we're at it. UPDATE #textmode SET inputbuffer = replace(replace(i.inputbuffer, char(10), ' '), char(13), ' ') FROM #textmode t JOIN @inputbuffer i ON CASE WHEN t.spid NOT LIKE '%/%' THEN convert(int, t.spid) END = i.spid OPTION (KEEPFIXED PLAN) IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Adjusting result set for text mode, time %d ms.', 0, 1, @ms) WITH NOWAIT END -- Mark last row. UPDATE #textmode SET last = 1 FROM #textmode f1 JOIN (SELECT spid, ident = MAX(ident) FROM (SELECT ident, spid = substring(spid, 1, coalesce(nullif( charindex('-', spid, 2) - 1, -1), len(spid))) FROM #textmode) AS x GROUP BY spid) AS f2 ON f2.ident = f1.ident OPTION (KEEPFIXED PLAN) -- Local varibles for the max lengths of all columns. DECLARE @spidlen varchar(5), @commandlen varchar(5), @loginlen varchar(5), @hostlen varchar(5), @hostprclen varchar(5), @endpointlen varchar(5), @appllen varchar(5), @dbnamelen varchar(5), @prcstatuslen varchar(5), @opntrnlen varchar(5), @trninfolen varchar(5), @blkbylen varchar(5), @cntlen varchar(5), @objectlen varchar(5), @rsctypelen varchar(5), @locktypelen varchar(5), @lstatuslen varchar(5), @ownertypelen varchar(5), @rscsubtypelen varchar(5), @waittimelen varchar(5), @waittypelen varchar(5), @cpulen varchar(5), @physiolen varchar(5), @logreadslen varchar(5), @tempdblen varchar(5), @login_timelen varchar(5), @last_batchlen varchar(5), @trn_startlen varchar(5), @last_sincelen varchar(5), @trn_sincelen varchar(5), @inputbufferlen varchar(5), @current_splen varchar(5) -- Get all maxlengths SELECT @spidlen = convert(varchar(5), coalesce(nullif(max(len(spid)), 0), 1)), @commandlen = convert(varchar(5), coalesce(nullif(max(len(command)), 0), 1)), @loginlen = convert(varchar(5), coalesce(nullif(max(len(login)), 0), 1)), @hostlen = convert(varchar(5), coalesce(nullif(max(len(host)), 0), 1)), @hostprclen = convert(varchar(5), coalesce(nullif(max(len(hostprc)), 0), 1)), @endpointlen = convert(varchar(5), coalesce(nullif(max(len(endpoint)), 0), 1)), @appllen = convert(varchar(5), coalesce(nullif(max(len(appl)), 0), 1)), @dbnamelen = convert(varchar(5), coalesce(nullif(max(len(dbname)), 0), 1)), @prcstatuslen = convert(varchar(5), coalesce(nullif(max(len(prcstatus)), 0), 1)), @opntrnlen = convert(varchar(5), coalesce(nullif(max(len(opntrn)), 0), 1)), @trninfolen = convert(varchar(5), coalesce(nullif(max(len(trninfo)), 0), 1)), @blkbylen = convert(varchar(5), coalesce(nullif(max(len(blkby)), 0), 1)), @cntlen = convert(varchar(5), coalesce(nullif(max(len(cnt)), 0), 1)), @objectlen = convert(varchar(5), coalesce(nullif(max(len(object)), 0), 1)), @rsctypelen = convert(varchar(5), coalesce(nullif(max(len(rsctype)), 0), 1)), @locktypelen = convert(varchar(5), coalesce(nullif(max(len(locktype)), 0), 1)), @lstatuslen = convert(varchar(5), coalesce(nullif(max(len(lstatus)), 0), 1)), @ownertypelen = convert(varchar(5), coalesce(nullif(max(len(ownertype)), 0), 1)), @rscsubtypelen = convert(varchar(5), coalesce(nullif(max(len(rscsubtype)), 0), 1)), @waittimelen = convert(varchar(5), coalesce(nullif(max(len(waittime)), 0), 1)), @waittypelen = convert(varchar(5), coalesce(nullif(max(len(waittype)), 0), 1)), @cpulen = convert(varchar(5), coalesce(nullif(max(len(cpu)), 0), 1)), @physiolen = convert(varchar(5), coalesce(nullif(max(len(physio)), 0), 1)), @logreadslen = convert(varchar(5), coalesce(nullif(max(len(logreads)), 0), 1)), @tempdblen = convert(varchar(5), coalesce(nullif(max(len(tempdb)), 0), 1)), @login_timelen = convert(varchar(5), coalesce(nullif(max(len(login_time)), 0), 1)), @last_batchlen = convert(varchar(5), coalesce(nullif(max(len(last_batch)), 0), 1)), @trn_startlen = convert(varchar(5), coalesce(nullif(max(len(trn_start)), 0), 1)), @last_sincelen = convert(varchar(5), coalesce(nullif(max(len(ltrim(last_since))), 0), 1)), @trn_sincelen = convert(varchar(5), coalesce(nullif(max(len(ltrim(trn_since))), 0), 1)), @inputbufferlen = convert(varchar(5), coalesce(nullif(max(len(inputbuffer)), 0), 1)), @current_splen = convert(varchar(5), coalesce(nullif(max(len(current_sp)), 0), 1)) FROM #textmode OPTION (KEEPFIXED PLAN) -- Remove line breaks in current statement UPDATE #textmode SET curstmt = replace(replace(curstmt, char(10), ''), char(13), '') WHERE len(curstmt) > 0 OPTION (KEEPFIXED PLAN) -- Return the #textdata table with dynamic lengths. IF @debug = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Returning result set, time %d ms.', 0, 1, @ms) WITH NOWAIT END EXEC ('SELECT spid = convert(varchar( ' + @spidlen + '), spid), command = convert(varchar( ' + @commandlen + '), command), login = convert(nvarchar( ' + @loginlen + '), login), host = convert(nvarchar( ' + @hostlen + '), host), hostprc = convert(varchar( ' + @hostprclen + '), hostprc), endpoint = convert(varchar( ' + @endpointlen + '), endpoint), appl = convert(nvarchar( ' + @appllen + '), appl), dbname = convert(nvarchar( ' + @dbnamelen + '), dbname), prcstatus = convert(varchar( ' + @prcstatuslen + '), prcstatus), spid_ = convert(varchar( ' + @spidlen + '), spid), opntrn = convert(varchar( ' + @opntrnlen + '), opntrn), trninfo = convert(varchar( ' + @trninfolen + '), trninfo), blklvl, blkby = convert(varchar( ' + @blkbylen + '), blkby), cnt = convert(varchar( ' + @cntlen + '), cnt), object = convert(nvarchar( ' + @objectlen + '), object), rsctype = convert(varchar( ' + @rsctypelen + '), rsctype), locktype = convert(varchar( ' + @locktypelen + '), locktype), lstatus = convert(varchar( ' + @lstatuslen + '), lstatus), ownertype = convert(varchar( ' + @ownertypelen + '), ownertype), rscsubtype = convert(varchar( ' + @rscsubtypelen + '), rscsubtype), waittime = convert(varchar( ' + @waittimelen + '), waittime), waittype = convert(varchar( ' + @waittypelen + '), waittype), spid__ = convert(varchar( ' + @spidlen + '), spid), cpu = convert(varchar( ' + @cpulen + '), cpu), physio = convert(varchar( ' + @physiolen + '), physio), logreads = convert(varchar( ' + @logreadslen + '), logreads), tempdb = convert(varchar( ' + @tempdblen + '), tempdb), now, login_time = convert(varchar( ' + @login_timelen + '), login_time), last_batch = convert(varchar( ' + @last_batchlen + '), last_batch), trn_start = convert(varchar( ' + @trn_startlen + '), trn_start), last_since = convert(varchar( ' + @last_sincelen + '), ltrim(last_since)), trn_since = convert(varchar( ' + @trn_sincelen + '), ltrim(trn_since)), clr, nstlvl, spid___ = convert(varchar( ' + @spidlen + '), spid), inputbuffer = convert(nvarchar( ' + @inputbufferlen + '), inputbuffer), current_sp = convert(nvarchar( ' + @current_splen + '), current_sp), curstmt, CASE last WHEN 1 THEN char(10) ELSE '' '' END FROM #textmode ORDER BY ident OPTION (KEEPFIXED PLAN)') END IF @debug = 1 AND @@nestlevel = 1 BEGIN SELECT @ms = datediff(ms, @now, getdate()) RAISERROR ('Completed, time %d ms.', 0, 1, @ms) WITH NOWAIT END GO /****** Object: StoredProcedure [dbo].[utility_EmailHtmlStringToHtmlTable] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: send the text as html report -- ============================================= CREATE PROCEDURE [dbo].[utility_EmailHtmlStringToHtmlTable] ( @p_Subject NVARCHAR(200), @p_HtmlString NVARCHAR(MAX) ) AS BEGIN --send email by send inti db email EXEC dbo.utility_SendInitDBEmail @p_Subject=@p_Subject, @p_Body=@p_HtmlString END GO /****** Object: StoredProcedure [dbo].[utility_EmailProcedureToHtmlTable] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Send the procedure result by html report -- ============================================= CREATE PROCEDURE [dbo].[utility_EmailProcedureToHtmlTable] ( @p_Subject NVARCHAR(200), @p_Procedure NVARCHAR(MAX) ) AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_Subject NVARCHAR(200) DECLARE @l_SqlQuery NVARCHAR(MAX) SET @l_SqlQuery='SELECT * FROM OPENQUERY(HelpServer,'''+@p_Procedure+''')' EXEC dbo.utility_EmailQueryToHtmlTable @p_Subject=@p_Subject, @p_SqlQuery=@l_SqlQuery END GO /****** Object: StoredProcedure [dbo].[utility_EmailQueryToHtmlTable] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Send the query's result by html report -- ============================================= CREATE PROCEDURE [dbo].[utility_EmailQueryToHtmlTable] ( @p_Subject NVARCHAR(200), @p_SqlQuery NVARCHAR(MAX) ) AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_Html NVARCHAR(MAX) DECLARE @l_QHeader NVARCHAR(MAX) DECLARE @l_QColumn NVARCHAR(MAX) DECLARE @l_TColumn NVARCHAR(MAX) DECLARE @l_TQuery NVARCHAR(MAX) DECLARE @l_CSS NVARCHAR(MAX) SET @l_Html ='' SET @l_QHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_CSS= '<style type="text/css"> table.gridtable { font-family: verdana,arial,sans-serif; font-size:11px; color:#333333; border-width: 1px; border-color: #666666; border-collapse: collapse; } table.gridtable th { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #dedede;} table.gridtable td { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #ffffff;} </style>' SET @l_TQuery = 'SELECT * INTO #TColumns FROM ( ' + @p_SqlQuery + ') Temp ' SET @l_TQuery=@l_TQuery+ ' SELECT @l_TColumn = @l_TColumn + name + '', '' FROM tempdb.sys.columns WHERE object_id = object_id('+'''tempdb..#TColumns'''+')' SET @l_TQuery=@l_TQuery +' DROP TABLE tempdb..#TColumns' SET @l_TQuery=@l_TQuery + ' SET @l_TColumn = LEFT(@l_TColumn,LEN(@l_TColumn)-1)' EXECUTE sp_executesql @l_TQuery ,N'@l_TColumn NVARCHAR(MAX) OUTPUT',@l_TColumn OUTPUT SELECT @l_QColumn = @l_QColumn + 'ISNULL(' + 'CAST('+Value +' AS NVARCHAR(MAX))' +' ,'''')' + ' AS TD, ' FROM dbo.fn_SplitStringToTable(@l_TColumn,',') SET @l_QColumn = LEFT(@l_QColumn,LEN(@l_QColumn)-1) SELECT @l_QHeader = @l_QHeader + '<TH>' + Value + '</TH>' FROM dbo.fn_SplitStringToTable(@l_TColumn,',') SET @l_QHeader = '<TR>' + @l_QHeader + '</TR>' SET @l_TQuery = 'SET @Html = (SELECT ' + @l_QColumn + ' FROM ( ' + @p_SqlQuery + ') AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS)' SELECT @l_TQuery EXECUTE sp_executesql @l_TQuery,N'@Html NVARCHAR(MAX) OUTPUT',@l_Html OUTPUT SET @l_Html = @l_CSS + REPLACE(@l_Html,'<TABLE>' ,'<TABLE class="gridtable">' + @l_QHeader) --send email by send inti db email EXEC dbo.utility_SendInitDBEmail @p_Subject=@p_Subject, @p_Body=@l_Html END GO /****** Object: StoredProcedure [dbo].[utility_INDEX_GetIndexFragementInfoForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get frgement info for all databases on a given server -- ============================================= CREATE PROCEDURE [dbo].[utility_INDEX_GetIndexFragementInfoForAllDatabase] @p_IsAlert BIT = 0 AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED CREATE TABLE #FragmentedIndexes ( DatabaseName NVARCHAR(200), SchemaName NVARCHAR(200), TableName NVARCHAR(200), IndexName NVARCHAR(200), [Fragmentation%] FLOAT ) EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #FragmentedIndexes SELECT DB_NAME(DB_ID()) AS DatabaseName, sc.name AS SchemaName, OBJECT_NAME (s.object_id) AS TableName, i.name AS IndexName, s.avg_fragmentation_in_percent AS [Fragmentation%] FROM sys.dm_db_index_physical_stats(db_id(),NULL, NULL, NULL,''SAMPLED'') s INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id INNER JOIN sys.objects o ON s.object_id = o.object_id INNER JOIN sys.schemas sc ON sc.[schema_id] = o.[schema_id] WHERE s.database_id = DB_ID() AND i.index_id != 0 AND s.record_count > 0 AND s.avg_fragmentation_in_percent>5 AND o.is_ms_shipped = 0 ;' --Generate rebuild/reorganize index script SELECT CASE WHEN [Fragmentation%] > 30 THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' REBUILD;' WHEN [Fragmentation%] > 10 THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' REORGANIZE;' END AS MaintanceScript INTO #TScript FROM #FragmentedIndexes WHERE [Fragmentation%] > 10 IF @p_IsAlert=0 SELECT * FROM #FragmentedIndexes SELECT * FROM #TScript --send alert report part IF EXISTS(SELECT 1 FROM #FragmentedIndexes WHERE @p_IsAlert=1 AND [Fragmentation%]>=10 ) BEGIN SELECT * INTO #TAlert FROM #FragmentedIndexes WHERE [Fragmentation%]>=10 SELECT * INTO #TAlert1 FROM #TScript DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) --for #TAlert part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Get Index Fragement From All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody --for #TAlert1 part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Get Index Fragement From All Database' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert1') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert1 AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TAlert DROP TABLE #TAlert1 END DROP TABLE #FragmentedIndexes DROP TABLE #TScript END GO /****** Object: StoredProcedure [dbo].[utility_INDEX_GetStatisticsStateInfoForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get statistics state info for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_INDEX_GetStatisticsStateInfoForAllDatabase] AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SET NOCOUNT ON SELECT DB_NAME() AS DBName, ss.name AS SchemaName, st.name AS TableName, s.name AS IndexName, STATS_DATE(s.id,s.indid) AS [Statistics Last Updated], s.rowcnt AS [Row Count], s.rowmodctr AS [Number Of Changes], CAST((CAST(s.rowmodctr AS DECIMAL(28,8))/CAST(s.rowcnt AS DECIMAL(28,2)) * 100.0) AS DECIMAL(28,2)) AS [% Rows Changed] INTO #TResult FROM sys.sysindexes s INNER JOIN sys.tables st ON st.[object_id] = s.[id] INNER JOIN sys.schemas ss ON ss.[schema_id] = st.[schema_id] WHERE 1=2 EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #TResult SELECT DB_NAME() AS DBName, ss.name AS SchemaName, st.name AS TableName, s.name AS IndexName, STATS_DATE(s.id,s.indid) AS [Statistics Last Updated], s.rowcnt AS [Row Count], s.rowmodctr AS [Number Of Changes], CAST((CAST(s.rowmodctr AS DECIMAL(28,8))/CAST(s.rowcnt AS DECIMAL(28,2)) * 100.0) AS DECIMAL(28,2)) AS [% Rows Changed] FROM sys.sysindexes s INNER JOIN sys.tables st ON st.[object_id] = s.[id] INNER JOIN sys.schemas ss ON ss.[schema_id] = st.[schema_id] WHERE s.id > 100 AND s.indid > 0 AND s.rowcnt >= 500 ORDER BY SchemaName, TableName, IndexName' SELECT * FROM #TResult DROP TABLE #TResult END GO /****** Object: StoredProcedure [dbo].[utility_INDEX_GetTopMissingIndexForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- Purpose: -- Create Date: 08/29/2012 -- Last Update: 08/29/2012 -- Author: Alex Tian CREATE PROCEDURE [dbo].[utility_INDEX_GetTopMissingIndexForAllDatabase] @p_IsAlert BIT = 0 AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 'CREATE NONCLUSTERED INDEX '+ QUOTENAME('IX_AutoGenerated_'+ REPLACE(REPLACE(CONVERT(VARCHAR(25), GETDATE(), 113), ' ', '_'), ':', '_')+ '_' + CAST(d.index_handle AS VARCHAR(22)))+ ' ON ' + d.[statement] + '('+ CASE WHEN d.equality_columns IS NULL THEN d.inequality_columns WHEN d.inequality_columns IS NULL THEN d.equality_columns ELSE d.equality_columns + ',' + d.inequality_columns END + ')'+ CASE WHEN d.included_columns IS NOT NULL THEN ' INCLUDE ( ' + d.included_columns + ')' ELSE '' END AS MissingIndexSQL, ROUND(s.avg_total_user_cost * s.avg_user_impact * (s.user_seeks + s.user_scans),0) AS [Total Cost], d.[statement] AS [Table Name], d.equality_columns, d.inequality_columns, d.included_columns INTO #MissingIndexes FROM sys.dm_db_missing_index_groups g INNER JOIN sys.dm_db_missing_index_group_stats s ON s.group_handle = g.index_group_handle INNER JOIN sys.dm_db_missing_index_details d ON d.index_handle = g.index_handle ORDER BY [Total Cost] DESC SELECT MissingIndexSQL AS MaintanceScript INTO #TScript FROM #MissingIndexes IF @p_IsAlert=0 SELECT * FROM #MissingIndexes SELECT * FROM #TScript --send alert report part IF EXISTS(SELECT 1 FROM #MissingIndexes WHERE @p_IsAlert=1) BEGIN SELECT * INTO #TAlert FROM #MissingIndexes SELECT * INTO #TAlert1 FROM #TScript DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) --for #TAlert part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Get Top Missing Index' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody --for #TAlert1 part SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Get Top Missing Index' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert1') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert1 AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TAlert DROP TABLE #TAlert1 END DROP TABLE #MissingIndexes DROP TABLE #TScript END GO /****** Object: StoredProcedure [dbo].[utility_INDEX_GetUnusedIndexForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Find unused indexes for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_INDEX_GetUnusedIndexForAllDatabase] AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SET NOCOUNT ON SELECT DB_NAME() AS DatabaseName, SCHEMA_NAME(o.Schema_ID) AS SchemaName, OBJECT_NAME(s.[object_id]) AS TableName, i.name AS IndexName, s.user_updates, s.system_seeks + s.system_scans + s.system_lookups AS [System usage] INTO #TempUnusedIndexes FROM sys.dm_db_index_usage_stats s INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id INNER JOIN sys.objects o ON i.object_id = o.object_id WHERE 1=2 EXEC sp_MSforeachdb 'USE [?]; INSERT INTO #TempUnusedIndexes SELECT TOP 20 DB_NAME() AS DatabaseName, SCHEMA_NAME(o.Schema_ID) AS SchemaName, OBJECT_NAME(s.[object_id]) AS TableName, i.name AS IndexName, s.user_updates, s.system_seeks + s.system_scans + s.system_lookups AS [System usage] FROM sys.dm_db_index_usage_stats s INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id INNER JOIN sys.objects o ON i.object_id = o.object_id WHERE s.database_id = DB_ID() AND OBJECTPROPERTY(s.[object_id], ''IsMsShipped'') = 0 AND user_seeks = 0 AND user_scans = 0 AND user_lookups = 0 AND i.name IS NOT NULL ORDER BY user_updates DESC' DECLARE @DisableOrDrop INT DECLARE @DisableIndexesSQL NVARCHAR(MAX) SET @DisableOrDrop = 1 SET @DisableIndexesSQL = '' SELECT CASE WHEN @DisableOrDrop = 1 THEN CHAR(10) + 'ALTER INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) + ' DISABLE;' ELSE CHAR(10) + 'DROP INDEX ' + QUOTENAME(IndexName) + ' ON ' + QUOTENAME(DatabaseName) + '.'+ QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName) END AS MaintanceScript INTO #TMS FROM #TempUnusedIndexes SELECT * FROM #TempUnusedIndexes SELECT * FROM #TMS DROP TABLE #TempUnusedIndexes DROP TABLE #TMS END GO /****** Object: StoredProcedure [dbo].[utility_IO_GetIOStallAtFileLevelForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Finding IO stall at file level -- ============================================= CREATE PROCEDURE [dbo].[utility_IO_GetIOStallAtFileLevelForAllDatabase] AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SET NOCOUNT ON SELECT DB_NAME(database_id) AS [DatabaseName], file_id, SUM(CAST(io_stall / 1000.0 AS DECIMAL(20,2))) AS [IO stall (secs)], SUM(CAST(num_of_bytes_read / 1024.0 / 1024.0 AS DECIMAL(20,2))) AS [IO read (MB)], SUM(CAST(num_of_bytes_written / 1024.0 / 1024.0 AS DECIMAL(20,2))) AS [IO written (MB)], SUM(CAST((num_of_bytes_read + num_of_bytes_written)/ 1024.0 / 1024.0 AS DECIMAL(20,2))) AS [TotalIO (MB)] FROM sys.dm_io_virtual_file_stats(NULL, NULL) GROUP BY database_id, file_id ORDER BY [IO stall (secs)] DESC END GO /****** Object: StoredProcedure [dbo].[utility_IO_GetIOWaitAtFileLevelForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Finding database file io waits -- ============================================= CREATE PROCEDURE [dbo].[utility_IO_GetIOWaitAtFileLevelForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DB_NAME(database_id) AS [Database Name] , file_id AS [File ID], io_stall_read_ms AS [Total Read Waits (ms)], num_of_reads AS [Number of Reads], CAST(io_stall_read_ms / ( 1.0 + num_of_reads ) AS NUMERIC(10, 1)) AS [Average Read Wait (ms)] , io_stall_write_ms AS [Total Write Waits (ms)], num_of_writes AS [Number of Writes], CAST(io_stall_write_ms / ( 1.0 + num_of_writes ) AS NUMERIC(10, 1)) AS [Average Write Wait (ms)] , io_stall_read_ms + io_stall_write_ms AS [Total I/O Waits (ms)] , num_of_reads + num_of_writes AS [Number of I/O Operations] , CAST(( io_stall_read_ms + io_stall_write_ms ) / ( 1.0 + num_of_reads + num_of_writes)AS NUMERIC(10,1)) AS [Average I/O Wait (ms)] FROM sys.dm_io_virtual_file_stats(NULL, NULL) ORDER BY [Average I/O Wait (ms)] DESC ; END GO /****** Object: StoredProcedure [dbo].[utility_IO_GetTotalReadWriteTimesForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Finding the total reads and writes for each database -- ============================================= CREATE PROCEDURE [dbo].[utility_IO_GetTotalReadWriteTimesForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT DB_NAME(qt.dbid) AS DatabaseName, SUM(qs.total_logical_reads) AS [Total Reads], SUM(qs.total_logical_writes) AS [Total Writes] FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt GROUP BY DB_NAME(qt.dbid) ORDER BY [Total Reads] DESC,[Total Writes] DESC END GO /****** Object: StoredProcedure [dbo].[utility_JOB_GetJobSummaryInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- Purpose: get job summary list -- Create Date: 08/29/2012 -- Last Update: 08/29/2012 -- Author: Alex Tian CREATE PROCEDURE [dbo].[utility_JOB_GetJobSummaryInfo] @p_IsAlert BIT=0, --Report need more restrict @p_JobName VARCHAR(255) = NULL, -- Optional job name filter @p_ShowDisabled BIT = 0, -- Include disabled jobs? @p_ShowUnscheduled BIT = 0, -- Include Unscheduled jobs? @p_JobThresholdSec INT = 0, -- If positive, show only the jobs with LAST duration above this. @p_AvgExecThresholdSec INT = 0 -- If positive, show only the jobs with AVERAGE duration above this. AS BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT * INTO #TJob FROM ( SELECT JobName, ISNULL(LastStep,'') LastStep, CASE WHEN StartDate IS NOT NULL AND FinishDate IS NULL THEN 'Running' WHEN Enabled = 0 THEN 'Disabled' WHEN StepCount = 0 THEN 'No steps' WHEN RunStatus IS NOT NULL THEN RunStatus WHEN ScheduleCount = 0 THEN 'Not scheduled' ELSE 'UNKNOWN' END Info, DatabaseName, Enabled, ScheduleCount, StepCount, StartDate, FinishDate, DurationSec, RIGHT('0'+convert(varchar(5),DurationSec/3600),2)+':'+ RIGHT('0'+convert(varchar(5),DurationSec%3600/60),2)+':'+ RIGHT('0'+convert(varchar(5),(DurationSec%60)),2) DurationSecFormatted, avgDurationSec, RIGHT('0'+convert(varchar(5),avgDurationSec/3600),2)+':'+ RIGHT('0'+convert(varchar(5),avgDurationSec%3600/60),2)+':'+ RIGHT('0'+convert(varchar(5),(avgDurationSec%60)),2) avgDurationSecFormatted, CASE WHEN (DurationSec IS NULL OR ISNULL(avgDurationSec, 0) = 0) THEN 0 ELSE CONVERT(DECIMAL(18,2), (100*CAST(DurationSec AS DECIMAL)) / CAST (avgDurationSec as DECIMAL)) END AS DurationRatio, NextRunDate, StepCommand, HistoryMessage FROM ( SELECT j.name JobName, j.enabled Enabled, (SELECT COUNT(1) FROM msdb..sysjobschedules jss WHERE jss.job_id = j.job_id) ScheduleCount, (SELECT COUNT(1) FROM msdb..sysjobsteps jps WHERE jps.job_id = j.job_id) StepCount, ls1.job_history_id HistoryID, ls1.start_execution_date StartDate, ls1.stop_execution_date FinishDate, ls1.last_executed_step_id LastStepID, DATEDIFF(SECOND, ls1.start_execution_date, CASE WHEN ls1.stop_execution_date IS NULL THEN GETDATE() ELSE ls1.stop_execution_date END) DurationSec, ISNULL(avgSec, 0) avgDurationSec, ls1.next_scheduled_run_date NextRunDate, st.step_name LastStep, st.command StepCommand, st.database_name DatabaseName, h.message HistoryMessage, CASE WHEN h.job_id IS NULL THEN 'Never Run' ELSE CASE h.run_status WHEN 0 THEN 'Failed' WHEN 1 THEN 'Succeeded' WHEN 2 THEN 'Retry' WHEN 3 THEN 'Canceled' END END RunStatus, h.run_date rawRunDate, h.run_time rawRunTime, h.run_duration rawRunDuration FROM msdb..sysjobactivity ls1 (NOLOCK) INNER JOIN msdb..sysjobs j (NOLOCK) ON ls1.job_id = j.job_id INNER JOIN (SELECT job_id JobID, MAX(session_id) LastSessionID FROM msdb..sysjobactivity (NOLOCK) GROUP BY job_id ) ls2 ON ls1.job_id = ls2.JobID AND ls1.session_id = ls2.LastSessionID LEFT OUTER JOIN msdb..sysjobsteps st (NOLOCK) ON st.job_id = j.job_id AND ls1.last_executed_step_id = st.step_id LEFT OUTER JOIN msdb..sysjobhistory h (NOLOCK) ON h.instance_id = ls1.job_history_id LEFT OUTER JOIN ( SELECT j.job_id JobID, SUM(h.avgSecs) avgSec FROM msdb..sysjobs j (NOLOCK) INNER JOIN ( SELECT job_id, step_id, AVG(run_duration/10000*3600 + run_duration%10000/100*60 + run_duration%100) avgSecs FROM msdb..sysjobhistory WHERE step_id > 0 AND run_status = 1 GROUP BY job_id, step_id ) h ON j.job_id = h.job_id GROUP BY j.job_id ) jobavg ON jobavg.JobID = j.job_id )jj WHERE (@p_ShowDisabled = 1 OR (StartDate IS NOT NULL AND FinishDate IS NULL) OR Enabled = 1) AND (@p_JobName IS NULL OR JobName = @p_JobName) AND (@p_ShowUnscheduled = 1 OR (StartDate IS NOT NULL AND FinishDate IS NULL) OR ScheduleCount > 0) AND (@p_JobThresholdSec = 0 OR DurationSec >= @p_JobThresholdSec) AND (@p_AvgExecThresholdSec = 0 OR avgDurationSec >= @p_AvgExecThresholdSec))x ORDER BY CASE Info WHEN 'Running' THEN 0 WHEN 'Failed' THEN 1 WHEN 'Retry' THEN 2 WHEN 'Succeeded' THEN 3 WHEN 'Canceled' THEN 4 WHEN 'No steps' THEN 5 WHEN 'Not scheduled' THEN 6 WHEN 'Disabled' THEN 7 WHEN 'Never Run' THEN 8 WHEN 'UNKNOWN' THEN -1 ELSE -2 END, NextRunDate, JobName IF @p_IsAlert=0 SELECT * FROM #TJob --send alert report part IF EXISTS(SELECT 1 FROM #TJob WHERE @p_IsAlert=1 AND Info IN ('Failed','UNKNOWN','Never Run','Disabled','No steps','Canceled') ) BEGIN SELECT * INTO #TAlert FROM #TJob WHERE Info IN ('Failed','UNKNOWN','Never Run','Disabled','No steps','Canceled') DECLARE @l_Html NVARCHAR(max) DECLARE @l_HHeader NVARCHAR(max) DECLARE @l_QColumn NVARCHAR(max) DECLARE @l_TColumn NVARCHAR(max) DECLARE @l_TQuery NVARCHAR(max) DECLARE @l_EmailSubject NVARCHAR(200) DECLARE @l_EmailBody NVARCHAR(max) SET @l_Html ='' SET @l_HHeader ='' SET @l_QColumn ='' SET @l_TColumn ='' SET @l_TQuery ='' SET @l_EmailSubject='Schedule Job Summary' SET @l_EmailBody='' SELECT @l_TColumn = @l_TColumn + name + ',' FROM tempdb.sys.columns WHERE object_id = object_id('tempdb..#TAlert') SET @l_TColumn=LEFT(@l_TColumn, LEN(@l_TColumn) - 1) SET @l_QColumn=dbo.fn_SplitStringToQueryColumn(@l_TColumn, ',') SET @l_HHeader=dbo.fn_SplitStringToHtmlHeader(@l_TColumn, ',') SET @l_TQuery = 'SET @Html = ( SELECT ' + @l_QColumn + ' FROM #TAlert AS TR FOR XML RAW(''TR'') ,ROOT(''TABLE''), ELEMENTS )' EXECUTE sp_executesql @l_TQuery, N'@Html NVARCHAR(MAX) OUTPUT', @l_Html OUTPUT SET @l_EmailBody=dbo.fn_FormatHtmlTable(@l_Html, @l_HHeader) EXECUTE dbo.utility_EmailHtmlStringToHtmlTable @p_Subject=@l_EmailSubject, @p_HtmlString=@l_EmailBody DROP TABLE #TAlert END DROP TABLE #TJob END GO /****** Object: StoredProcedure [dbo].[utility_LOG_GetCustomSQLErrorLog] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get error log from application -- ============================================= CREATE PROCEDURE [dbo].[utility_LOG_GetCustomSQLErrorLog] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_TimeStart DATETIME SET @l_TimeStart=DATEADD(DAY,-1,GETDATE()); SELECT * FROM dbo.ErrorLog WHERE DATEDIFF(DAY,Time,GETDATE())<=1 ORDER BY DBName,Time DESC END GO /****** Object: StoredProcedure [dbo].[utility_LOG_GetSQLAgentLog] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get sql server error log -- 1.Value of error log file you want to read: 0 = current, 1 = Archive #1, 2 = Archive #2, etc... -- 2.Log file type: 1 or NULL = error log, 2 = SQL Agent log -- 3.Search string 1: String one you want to search for -- 4.Search string 2: String two you want to search for to further refine the results -- ============================================= CREATE PROCEDURE [dbo].[utility_LOG_GetSQLAgentLog] ( @p_p1 INT = 0, @p_p2 INT = 2, @p_p3 VARCHAR(255) = NULL, @p_p4 VARCHAR(255) = NULL ) AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_TimeStart DATETIME DECLARE @l_TimeEnd DATETIME SET @l_TimeStart=DATEADD(DAY,-1,GETDATE()); SET @l_TimeEnd=GETDATE(); IF (NOT IS_SRVROLEMEMBER(N'securityadmin') = 1) BEGIN RAISERROR(15003,-1,-1, N'securityadmin') RETURN (1) END IF (@p_p2 IS NULL) EXEC master.sys.xp_readerrorlog @p_p1 ELSE EXEC master.sys.xp_readerrorlog @p_p1,@p_p2,@p_p3,@p_p4,@l_TimeStart,@l_TimeEnd END GO /****** Object: StoredProcedure [dbo].[utility_LOG_GetSQLServerErrorLog] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get sql server error log -- 1.Value of error log file you want to read: 0 = current, 1 = Archive #1, 2 = Archive #2, etc... -- 2.Log file type: 1 or NULL = error log, 2 = SQL Agent log -- 3.Search string 1: String one you want to search for -- 4.Search string 2: String two you want to search for to further refine the results -- ============================================= CREATE PROCEDURE [dbo].[utility_LOG_GetSQLServerErrorLog] ( @p_p1 INT = 0, @p_p2 INT = 1, @p_p3 VARCHAR(255) = NULL, @p_p4 VARCHAR(255) = NULL ) AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_TimeStart DATETIME DECLARE @l_TimeEnd DATETIME SET @l_TimeStart=DATEADD(DAY,-1,GETDATE()); SET @l_TimeEnd=GETDATE(); IF (NOT IS_SRVROLEMEMBER(N'securityadmin') = 1) BEGIN RAISERROR(15003,-1,-1, N'securityadmin') RETURN (1) END IF (@p_p2 IS NULL) EXEC master.sys.xp_readerrorlog @p_p1 ELSE EXEC master.sys.xp_readerrorlog @p_p1,@p_p2,@p_p3,@p_p4,@l_TimeStart,@l_TimeEnd END GO /****** Object: StoredProcedure [dbo].[utility_LOG_GetWeeklyEventLog] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get the latest event log -- ============================================= CREATE PROCEDURE [dbo].[utility_LOG_GetWeeklyEventLog] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED DECLARE @l_BeginDate SMALLDATETIME DECLARE @l_EndDate SMALLDATETIME DECLARE @l_DateNow SMALLDATETIME SET @l_DateNow = CONVERT(VARCHAR(10), GETDATE(), 120) SET @l_BeginDate = DATEADD(d, - DATEPART(dw, @l_DateNow) - 7, @l_DateNow) SET @l_EndDate = DATEADD(d, - DATEPART(dw, @l_DateNow), @l_DateNow) SELECT EventData.value('(/EVENT_INSTANCE/DatabaseName)[1]', 'varchar(128)') AS DatabaseName, EventData.value('(/EVENT_INSTANCE/EventType)[1]', 'varchar(128)') AS EventType, EventData.value('(/EVENT_INSTANCE/UserName)[1]', 'varchar(128)') AS UserName, EventData.value('(/EVENT_INSTANCE/LoginName)[1]', 'varchar(128)') AS LoginName, EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'datetime') AS PostTime, EventData.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)') AS CommandText FROM dbo.EventLog WHERE EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'smalldatetime') >= @l_BeginDate AND EventData.value('(/EVENT_INSTANCE/PostTime)[1]', 'smalldatetime') < @l_EndDate END GO /****** Object: StoredProcedure [dbo].[utility_MEMORY_GetBufferCacheHitRatio] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get the buffer cache hit ratio -- ============================================= CREATE PROCEDURE [dbo].[utility_MEMORY_GetBufferCacheHitRatio] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT (CAST(SUM(CASE LTRIM(RTRIM(counter_name)) WHEN 'Buffer cache hit ratio' THEN CAST(cntr_value AS INTEGER) ELSE NULL END) AS FLOAT) / CAST(SUM(CASE LTRIM(RTRIM(counter_name)) WHEN 'Buffer cache hit ratio base' THEN CAST(cntr_value AS INTEGER) ELSE NULL END) AS FLOAT)) * 100 AS BufferCacheHitRatio FROM sys.dm_os_performance_counters WITH (NOLOCK) WHERE [object_name] LIKE 'SQLServer:Buffer Manager%' AND [counter_name] LIKE 'Buffer cache hit ratio%' END GO /****** Object: StoredProcedure [dbo].[utility_MEMORY_GetMemoryUsedAtDatabaseLevelForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get memory used for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_MEMORY_GetMemoryUsedAtDatabaseLevelForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT ISNULL(DB_NAME(database_id), 'ResourceDb') AS DatabaseName, CAST(COUNT(row_count) * 8.0 / (1024.0) AS DECIMAL(28,2)) AS [Size (MB)] FROM sys.dm_os_buffer_descriptors GROUP BY database_id ORDER BY [Size (MB)] DESC ,DatabaseName END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetExtendedWhoProcedure] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Execute extended who procedure -- Some Sample Usage: -- EXEC dbo.query_GetExtendedWhoProcedure; -- EXEC dbo.query_GetExtendedWhoProcedure 'active'; -- EXEC dbo.query_GetExtendedWhoProcedure 'active',@IncludeSQL = 1,@Brief = 1; -- EXEC dbo.query_GetExtendedWhoProcedure 'active', @IncludeSelf = 1; -- EXEC dbo.query_GetExtendedWhoProcedure @Loginame = 'sa'; -- EXEC dbo.query_GetExtendedWhoProcedure @OrderBy = 'CPU_Time'; -- EXEC dbo.query_GetExtendedWhoProcedure @IncludeSystemSPIDs = 1; -- EXEC dbo.query_GetExtendedWhoProcedure @ShowBlockersOnly = 1; -- EXEC dbo.query_GetExtendedWhoProcedure @SearchSPID = 58; -- EXEC dbo.query_GetExtendedWhoProcedure @SearchDBName = 'SomeDatabaseName'; -- EXEC dbo.query_GetExtendedWhoProcedure @IncludeSQL = 1,@SearchCommand = '%update%sometable%'; -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetExtendedWhoProcedure] -- only show logins with this name @Loginame VARCHAR(255) = 'active', -- ShowBlockersOnly will reduce resultset to -- those that are blocking or being blocked @ShowBlockersOnly BIT = 0, -- optional search conditions @SearchSPID INT = NULL, @SearchDBName NVARCHAR(255) = '%', @SearchHostName NVARCHAR(255) = '%', @SearchCommand NVARCHAR(255) = '%', @SearchIP VARCHAR(16) = '%', @SearchProgramName NVARCHAR(255) = '%', -- unlikely you want to see yourself, -- but stranger things can happen @IncludeSelf BIT = 0, -- show system SPIDs? @IncludeSystemSPIDs BIT = 0, -- augment exec_sql info with DBCC INPUTBUFFER @IncludeSQL BIT = 1, -- displays only the first 255 characters of SQL @Brief BIT = 0, -- optional sorting... allowed values: -- 'Elapsed_Time', 'CPU_Time', -- 'Logical_Reads', 'Reads', 'Writes' @OrderBy VARCHAR(32) = NULL AS BEGIN SET NOCOUNT ON; SET ANSI_WARNINGS OFF; DECLARE @spid INT, @sql NVARCHAR(MAX), @briefsize SMALLINT; -- used in conjunction with @Brief and @IncludeSQL SET @briefsize = 255; -- override @IncludeSQL otherwise nothing to search IF @SearchCommand != '%' SET @IncludeSQL = 1; SELECT [Spid] = s.[session_id], [Status] = MAX(UPPER(COALESCE ( r.[status], tt.[task_state], s.[status], '' ))), [Command] = MAX(COALESCE ( r.[command], r.[wait_type], wt.[wait_type], r.[last_wait_type], '' )), [Blocked_By] = MAX(CONVERT(VARCHAR(12), COALESCE ( RTRIM(NULLIF(r.[blocking_session_id], 0)), ' .' ))), [Database_Name] = MAX(DB_NAME(COALESCE ( tl.[database_id], r.[database_id], t.[database_id], '' ))), [Logical_Reads] = MAX(COALESCE ( NULLIF(r.[logical_reads], 0), s.[logical_reads], 0 )), [Reads] = MAX(COALESCE ( NULLIF(r.[reads], 0), NULLIF(s.[reads], 0), c.[num_reads], 0 )), [Writes] = MAX(COALESCE ( NULLIF(r.[writes], 0), NULLIF(s.[writes], 0), c.[num_writes], 0 )), [CPU_Time] = MAX(COALESCE ( NULLIF(tt.[CPU_Time], 0), NULLIF(r.[cpu_time], 0), NULLIF(s.[cpu_time], 0), s.[total_scheduled_time], 0 )), [Elapsed_Time] = MAX(COALESCE ( r.[total_elapsed_time], s.[total_elapsed_time] )), [Row_Count] = MAX(s.[row_count]), [Memory_In_Pages] = MAX(COALESCE ( NULLIF(r.[granted_query_memory], 0), s.[memory_usage], 0 )), [Tran_Count] = MAX(COALESCE ( t.[trancount], 0 )), [Lock_Count] = MAX(COALESCE ( tl.[lockcount], 0 )), [Login_Name] = s.[login_name], [Host_Name] = MAX(COALESCE ( s.[host_name], ' .' )), [IP_Address] = MAX(COALESCE ( c.[client_net_address], ' .' )), [Program_Name] = MAX(COALESCE ( s.[program_name], '' )), [Login_Time] = MAX(COALESCE ( s.[login_time], c.[connect_time] )), [Last_Request] = MAX(COALESCE ( r.[start_time], s.[last_request_start_time] )), [Handle] = MAX(COALESCE ( r.[sql_handle], c.[most_recent_sql_handle] )), [Exec_SQL] = CONVERT(NVARCHAR(MAX), N'') INTO #spids FROM sys.dm_exec_sessions s LEFT OUTER JOIN sys.dm_exec_connections c ON c.[session_id] = s.[session_id] LEFT OUTER JOIN sys.dm_exec_requests r ON s.[session_id] = r.[session_id] LEFT OUTER JOIN ( SELECT [session_id], [database_id] = MAX([database_id]), [trancount] = COUNT(*) FROM sys.dm_tran_session_transactions t INNER JOIN sys.dm_tran_database_transactions dt ON t.[transaction_id] = dt.[transaction_id] GROUP BY [session_id] ) t ON s.[session_id] = t.[session_id] LEFT OUTER JOIN ( SELECT [request_session_id], [database_id] = MAX([resource_database_id]), [lockcount] = COUNT(*) FROM sys.dm_tran_locks WITH (NOLOCK) GROUP BY [request_session_id] ) tl ON s.[session_id] = tl.[request_session_id] LEFT OUTER JOIN sys.dm_os_waiting_tasks wt ON s.[session_id] = wt.[session_id] LEFT OUTER JOIN ( SELECT ot.[session_id], ot.[task_state], [CPU_Time] = MAX(oth.[usermode_time]) FROM sys.dm_os_tasks ot INNER JOIN sys.dm_os_workers ow ON ot.[worker_address] = ow.[worker_address] INNER JOIN sys.dm_os_threads oth ON ow.[thread_address] = oth.[thread_address] GROUP BY ot.[session_id], ot.[task_state] ) tt ON s.[session_id] = tt.[session_id] WHERE s.[login_name] = COALESCE ( NULLIF(@Loginame, 'active'), s.[login_name] ) GROUP BY s.[session_id], s.[login_name]; -- delete rows we're not interested in IF LOWER(@Loginame) = 'active' BEGIN DELETE #spids WHERE UPPER([Status]) = 'SLEEPING' OR UPPER([Command]) = 'AWAITING COMMAND'; END IF @ShowBlockersOnly = 1 BEGIN DELETE s1 FROM #spids s1 WHERE s1.[Blocked_By] = ' .' AND NOT EXISTS ( SELECT 1 FROM #spids WHERE [Blocked_By] = RTRIM(s1.[Spid]) ); END IF @SearchSPID IS NOT NULL BEGIN DELETE #spids WHERE [Spid] != @SearchSPID; END IF @SearchDBName != '%' BEGIN DELETE #spids WHERE [Database_Name] IS NULL OR [Database_Name] NOT LIKE @SearchDBName; END IF @SearchHostName != '%' OR @SearchProgramName != '%' OR @SearchIP != '%' BEGIN DELETE #spids WHERE [Host_Name] NOT LIKE @SearchHostName OR [Program_Name] NOT LIKE @SearchProgramName OR [IP_Address] NOT LIKE @SearchIP; END IF @IncludeSelf = 0 BEGIN DELETE #spids WHERE [Spid] = @@SPID; END IF @IncludeSystemSPIDs = 0 BEGIN DELETE #spids WHERE [Spid] <= 50; END CREATE TABLE #dbcc ( a NVARCHAR(500), b NVARCHAR(500), [Input_Buffer] NVARCHAR(MAX), [Spid] INT NULL ); IF @IncludeSQL = 1 BEGIN UPDATE #spids SET [Exec_SQL] = ( SELECT [text] FROM sys.dm_exec_sql_text([Handle]) ); DECLARE dbcc_cursor CURSOR LOCAL FORWARD_ONLY STATIC READ_ONLY FOR SELECT [Spid] FROM #spids; OPEN dbcc_cursor; FETCH NEXT FROM dbcc_cursor INTO @spid; WHILE @@FETCH_STATUS = 0 BEGIN SET @sql = 'DBCC INPUTBUFFER(' +RTRIM(@spid)+') WITH NO_INFOMSGS;'; INSERT #dbcc(a,b,[Input_Buffer]) EXEC sp_executesql @sql; UPDATE #dbcc SET [Spid] = @spid WHERE [Spid] IS NULL; FETCH NEXT FROM dbcc_cursor INTO @spid; END CLOSE dbcc_cursor; DEALLOCATE dbcc_cursor; IF @SearchCommand != '%' BEGIN DELETE #dbcc WHERE COALESCE([Input_Buffer], '') NOT LIKE @SearchCommand; DELETE #spids WHERE COALESCE([Exec_SQL], '') NOT LIKE @SearchCommand; END IF @Brief = 1 BEGIN UPDATE #dbcc SET [Input_Buffer] = COALESCE(LEFT([Input_Buffer], @briefsize), ''); UPDATE #spids SET [Exec_SQL] = COALESCE(LEFT([Exec_SQL], @briefsize), ''); END END SELECT s.[Spid], s.[Status], s.[Command], s.[Blocked_By], s.[Database_Name], s.[Logical_Reads], s.[Reads], s.[Writes], s.[CPU_Time], s.[Elapsed_Time], s.[Row_Count], s.[Memory_In_Pages], s.[Tran_Count], s.[Lock_Count], s.[Login_Name], s.[Host_Name], s.[IP_Address], s.[Program_Name], s.[Login_Time], s.[Last_Request], s.[Exec_SQL], [Input_Buffer] = COALESCE(d.[Input_Buffer], '') FROM #spids s LEFT OUTER JOIN #dbcc d ON s.[Spid] = d.[Spid] ORDER BY CASE @OrderBy WHEN 'Elapsed_Time' THEN s.[Elapsed_Time] WHEN 'CPU_Time' THEN s.[CPU_Time] WHEN 'Logical_Reads' THEN s.[Logical_Reads] WHEN 'Reads' THEN s.[Reads] WHEN 'Writes' THEN s.[Writes] END DESC, s.[Spid]; DROP TABLE #dbcc, #spids; END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetTopLongestBlockedQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: The queries spend the longest time being blocked for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetTopLongestBlockedQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 CAST((qs.total_elapsed_time - qs.total_worker_time) /1000000.0 AS DECIMAL(28,2)) AS [Total time blocked (s)], CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time AS DECIMAL(28,2)) AS [% CPU], CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting], qs.execution_count, CAST((qs.total_elapsed_time - qs.total_worker_time) / 1000000.0/ qs.execution_count AS DECIMAL(28, 2)) AS [Blocking average (s)], SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_elapsed_time > 0 ORDER BY [Total time blocked (s)] DESC END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetTopLongestTimeQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: The queries that take the longest time to run for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetTopLongestTimeQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 CAST(qs.total_elapsed_time / 1000000.0 AS DECIMAL(28, 2))AS [Total Duration (s)], CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time AS DECIMAL(28, 2))AS [% CPU], CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting], qs.execution_count, CAST(qs.total_elapsed_time / 1000000.0 / qs.execution_count AS DECIMAL(28, 2))AS [Average Duration (s)], SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_elapsed_time > 0 ORDER BY qs.total_elapsed_time DESC END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetTopMostCPUCostQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get the queries that use the most CPU for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetTopMostCPUCostQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 CAST((qs.total_worker_time) / 1000000.0AS DECIMAL(28,2)) AS [Total CPU time (s)], CAST(qs.total_worker_time * 100.0 / qs.total_elapsed_time AS DECIMAL(28,2)) AS [% CPU], CAST((qs.total_elapsed_time - qs.total_worker_time)* 100.0 /qs.total_elapsed_time AS DECIMAL(28, 2)) AS [% Waiting], qs.execution_count, CAST((qs.total_worker_time) / 1000000.0/ qs.execution_count AS DECIMAL(28, 2)) AS [CPU time average (s)], SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp WHERE qs.total_elapsed_time > 0 ORDER BY [Total CPU time (s)] DESC END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetTopMostIOCostQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get the queries that use the most I/O -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetTopMostIOCostQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 [Total IO] = (qs.total_logical_reads + qs.total_logical_writes), [Average IO] = (qs.total_logical_reads + qs.total_logical_writes) /qs.execution_count, qs.execution_count, SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY [Total IO] DESC END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetTopMostOftenExecutedQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: The queries that have been executed the most often -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetTopMostOftenExecutedQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 qs.execution_count, SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid) AS DatabaseName, qp.query_plan FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp ORDER BY qs.execution_count DESC; END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetTopMostRecompiledQueryForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Determining your most-recompiled queries -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetTopMostRecompiledQueryForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT TOP 20 qs.plan_generation_num, qs.total_elapsed_time, qs.execution_count, SUBSTRING (qt.text,(qs.statement_start_offset/2) + 1,((CASE WHEN qs.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE qs.statement_end_offset END - qs.statement_start_offset)/2) + 1) AS [Individual Query], qt.text AS [Parent Query], DB_NAME(qt.dbid), qs.creation_time, qs.last_execution_time FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) as qt ORDER BY plan_generation_num DESC END GO /****** Object: StoredProcedure [dbo].[utility_QUERY_GetWhatProcessIsRunningForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get what process is running for all database -- ============================================= CREATE PROCEDURE [dbo].[utility_QUERY_GetWhatProcessIsRunningForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT der.session_id AS SessionID, der.status AS Status, des.login_name AS Login, des.[host_name] AS HostName, DB_NAME(der.database_id) AS DatabaseName, des.[program_name] AS Program, der.command AS Command, dest.text AS CommandText , des.cpu_time AS CPUTime, des.memory_usage*8 AS MemoryUsage_KB, des.reads AS Reads, des.writes AS Writes, des.logical_reads AS LogicalReads, des.total_scheduled_time AS TotalScheduleTime, des.login_time AS LoginTime, dec.client_net_address AS ClientNetAddress, des.client_interface_name AS ClientInterfaceName FROM sys.dm_exec_requests der INNER JOIN sys.dm_exec_connections dec ON der.session_id = dec.session_id INNER JOIN sys.dm_exec_sessions des ON des.session_id = der.session_id CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS dest ORDER BY CPUTime DESC ,MemoryUsage_KB DESC END GO /****** Object: StoredProcedure [dbo].[utility_SPACE_GetDiskSpaceForServer] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get disk space -- ============================================= CREATE PROCEDURE [dbo].[utility_SPACE_GetDiskSpaceForServer] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED IF @@microsoftversion / power(2, 24) >= 9 BEGIN EXEC sp_configure 'show advanced options', 1 RECONFIGURE WITH OVERRIDE EXEC sp_configure 'xp_cmdshell', 1 RECONFIGURE WITH OVERRIDE END DECLARE @hr int DECLARE @fso int DECLARE @drive char(1) DECLARE @odrive int DECLARE @TotalSize varchar(20) DECLARE @MB bigint ; SET @MB = 1048576 CREATE TABLE #drives (drive char(1) PRIMARY KEY, FreeSpace int NULL, TotalSize int NULL) INSERT #drives(drive,FreeSpace) EXEC master.dbo.xp_fixeddrives EXEC @hr=sp_OACreate 'Scripting.FileSystemObject',@fso OUT IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso DECLARE dcur CURSOR LOCAL FAST_FORWARD FOR SELECT drive FROM #drives ORDER BY drive OPEN dcur FETCH NEXT FROM dcur INTO @drive WHILE @@FETCH_STATUS=0 BEGIN EXEC @hr = sp_OAMethod @fso,'GetDrive', @odrive OUT, @drive IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso EXEC @hr = sp_OAGetProperty @odrive,'TotalSize', @TotalSize OUT IF @hr <> 0 EXEC sp_OAGetErrorInfo @odrive UPDATE #drives SET TotalSize=@TotalSize/@MB WHERE drive=@drive FETCH NEXT FROM dcur INTO @drive END CLOSE dcur DEALLOCATE dcur EXEC @hr=sp_OADestroy @fso IF @hr <> 0 EXEC sp_OAGetErrorInfo @fso SELECT drive, FreeSpace as 'Free(MB)', TotalSize as 'Total(MB)', CAST((FreeSpace/(TotalSize*1.0))*100.0 as int) as 'Free(%)' FROM #drives ORDER BY drive DROP TABLE #drives IF @@microsoftversion / power(2, 24) >= 9 BEGIN EXEC sp_configure 'xp_cmdshell', 0 RECONFIGURE WITH OVERRIDE EXEC sp_configure 'show advanced options', 0 RECONFIGURE WITH OVERRIDE END END GO /****** Object: StoredProcedure [dbo].[utility_SPACE_GetLogSizeForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get database log size for each database -- ============================================= create PROCEDURE [dbo].[utility_SPACE_GetLogSizeForAllDatabase] AS BEGIN SET NOCOUNT ON --Displaying log space information for all databases --The following example displays LOGSPACE information for all databases contained in the instance of SQL Server DBCC SQLPERF(LOGSPACE); END GO /****** Object: StoredProcedure [dbo].[utility_SPACE_GetSizeAtFileLevelForAllDatabase] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get database size for each database -- ============================================= CREATE PROCEDURE [dbo].[utility_SPACE_GetSizeAtFileLevelForAllDatabase] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED -- Check to see the temp table exists IF EXISTS ( SELECT name FROM tempdb..sysobjects WHERE name LIKE '#HoldforEachDBSize%' ) DROP TABLE #HoldforEachDBSize CREATE TABLE #HoldforEachDBSize ( DatabaseName NVARCHAR(75) NOT NULL, Size DECIMAL NOT NULL, Name NVARCHAR(75) NOT NULL, Filename NVARCHAR(90) NOT NULL) IF EXISTS ( SELECT name FROM tempdb..sysobjects WHERE name LIKE '#FixedDrives%' ) DROP TABLE #FixedDrives CREATE TABLE #FixedDrives ( Drive CHAR(1) NOT NULL, MBFree DECIMAL NOT NULL) -- Insert rows from sp_MSForEachDB into temp table INSERT INTO #HoldforEachDBSize EXEC sp_MSforeachdb 'SELECT ''?'' AS DatabaseName, CASE WHEN [?]..sysfiles.size * 8 / 1024 = 0 THEN 1 ELSE [?]..sysfiles.size * 8 / 1024 END AS size, [?]..sysfiles.name AS Name, [?]..sysfiles.filename AS Filename FROM [?]..sysfiles' INSERT INTO #FixedDrives EXEC xp_fixeddrives SELECT RTRIM(CAST(DatabaseName AS VARCHAR(75))) AS DatabaseName, Drive AS Drive, Filename AS Filename, CAST(Size AS INT) AS Size, CAST(MBFree AS VARCHAR(10)) AS MB_Free FROM #HoldforEachDBSize INNER JOIN #FixedDrives ON LEFT(#HoldforEachDBSize.Filename, 1) = #FixedDrives.Drive GROUP BY DatabaseName, Drive, MBFree, Filename, CAST(Size AS INT) ORDER BY Drive, Size DESC SELECT Drive AS [Total Data Space Used], CAST(SUM(Size) AS VARCHAR(10)) AS [Total Size], CAST(MBFree AS VARCHAR(10)) AS MB_Free FROM #HoldforEachDBSize INNER JOIN #FixedDrives ON LEFT(#HoldforEachDBSize.Filename, 1) = #FixedDrives.Drive GROUP BY Drive, MBFree SELECT COUNT(DISTINCT RTRIM(CAST(DatabaseName AS VARCHAR(75)))) AS Database_Count FROM #HoldforEachDBSize DROP TABLE #FixedDrives DROP TABLE #HoldforEachDBSize END GO /****** Object: StoredProcedure [dbo].[utility_SendInitDBEmail] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: In order to modify configure easily , we init sp_send_dbmail first -- ============================================= CREATE PROCEDURE [dbo].[utility_SendInitDBEmail] ( @p_Subject NVARCHAR(200), @p_Body NVARCHAR(MAX) ) AS BEGIN SET @p_Subject= '[SQL Auto Email - '+ @@SERVERNAME + '] - '+ISNULL(@p_Subject,'') EXEC msdb.dbo.sp_send_dbmail @profile_name='Database Mail Public Profile', @recipients = '[email protected];[email protected];[email protected]', @subject = @p_Subject, @body = @p_Body, @body_format = 'HTML' END GO /****** Object: StoredProcedure [dbo].[utility_TEMPDB_GetTempdbSpaceInfo] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-01 -- Description: Get tempdb total space usage by object type -- ============================================= CREATE PROCEDURE [dbo].[utility_TEMPDB_GetTempdbSpaceInfo] AS BEGIN SET NOCOUNT ON SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT SUM (user_object_reserved_page_count) * (8.0/1024.0) AS [User Objects (MB)], SUM (internal_object_reserved_page_count) * (8.0/1024.0) AS [Internal Objects (MB)], SUM (version_store_reserved_page_count) * (8.0/1024.0) AS [Version Store (MB)], SUM (mixed_extent_page_count)* (8.0/1024.0) AS [Mixed Extent (MB)], SUM (unallocated_extent_page_count)* (8.0/1024.0) AS [Unallocated (MB)] FROM sys.dm_db_file_space_usage END GO /****** Object: UserDefinedFunction [dbo].[fn_FormatHtmlTable] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO create FUNCTION [dbo].[fn_FormatHtmlTable] ( @p_Html VARCHAR(MAX), @p_HtmlHeader VARCHAR(MAX) ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @l_CSS NVARCHAR(MAX) DECLARE @l_Output VARCHAR(MAX) SET @l_Output='' SET @l_CSS= '<style type="text/css"> table.gridtable { font-family: verdana,arial,sans-serif; font-size:11px; color:#333333; border-width: 1px; border-color: #666666; border-collapse: collapse; } table.gridtable th { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #dedede;} table.gridtable td { border-width: 1px; padding: 8px; border-style: solid; border-color: #666666; background-color: #ffffff;} </style>' SET @l_Output = @l_CSS + REPLACE(@p_Html,'<TABLE>' ,'<TABLE class="gridtable">' + @p_HtmlHeader) RETURN @l_Output END GO /****** Object: UserDefinedFunction [dbo].[fn_GetSQLBySPID] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Alex Tian -- Create date: 2012-09-03 -- Description: Get sql scirpt by SPID -- ============================================= CREATE FUNCTION [dbo].[fn_GetSQLBySPID] ( @p_SPID INT ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @l_Output VARCHAR(MAX) SET @l_Output='' DECLARE @sql_handle binary(20), @handle_found bit DECLARE @stmt_start int, @stmt_end int SELECT @sql_handle = sql_handle, @stmt_start = stmt_start/2, @stmt_end = CASE WHEN stmt_end = -1 THEN -1 ELSE stmt_end/2 END FROM master.dbo.sysprocesses WHERE spid = @p_SPID AND ecid = 0 SET @l_Output = (SELECT SUBSTRING( text, COALESCE(NULLIF(@stmt_start, 0), 1), CASE @stmt_end WHEN -1 THEN DATALENGTH(text) ELSE (@stmt_end - @stmt_start) END) FROM ::fn_get_sql(@sql_handle)) RETURN @l_Output END GO /****** Object: UserDefinedFunction [dbo].[fn_SplitStringToHtmlHeader] Script Date: 2012/9/7 9:36:10 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO CREATE FUNCTION [dbo].[fn_SplitStringToHtmlHeader] ( @p_Input VARCHAR(MAX), @p_Delimeter CHAR(1) = ',' ) RETURNS VARCHAR(MAX) AS BEGIN DECLARE @l_Output VARCHAR(MAX) SET @l_Output=