[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/bornsql/scripts/main/sp_SQL2000_helpindex.sql [Back]  [Original]

/*
	sp_SQL2000_helpindex.sql
	https://bornsql.ca/s/script-duplicate-index-finder/
	Copyright (c) BornSQL.ca
	Written by Randolph West, released under the MIT License
	Last updated: 19 June 2020

	Based on sp_helpindex from SQL Server 2000, this script outputs
	an index structure in the same format as the 2005+ script by
	Kimberly Tripp. This is written specifically for SQL Server 2000.

	This script is called by sp_SQL2000_finddupes

	See: https://www.sqlskills.com/blogs/kimberly/removing-duplicate-indexes/

	-- June 2020: Renamed files, fixed formatting, and improved comments.

	-- September 2013: Moved to GitHub.

	-- May 2013: Worked around RID / UNIQUIFIER not displaying correctly.

	-- August 2012: Updated copyright bits, cleaned up formatting and
	--			    comments.

	--  March 2012: Based on SQL Server 2000 sp_helpindex with revised
	--			    code for columns in index levels.
*/

USE master
GO

IF OBJECTPROPERTY(OBJECT_ID('sp_SQL2000_helpindex'), 'IsProcedure') = 1
	DROP PROCEDURE sp_SQL2000_helpindex
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[sp_SQL2000_helpindex] @objname NVARCHAR(776) -- the table to check for indexes
AS
BEGIN

	-- PRELIM
	SET NOCOUNT ON

	DECLARE @objid INT,		   -- the object id of the table
			@indid SMALLINT,	  -- the index id of an index
			@groupid SMALLINT,	-- the filegroup id of an index
			@indname sysname,
			@groupname sysname,
			@status INT,
			@keys NVARCHAR(2126), --Length (16*max_identifierLength)+(15*2)+(16*3)
			@dbname sysname

	-- Check to see that the object names are local to the current database.
	SELECT @dbname = PARSENAME(@objname, 3)

	IF @dbname IS NOT NULL
	   AND @dbname  DB_NAME()
	BEGIN
		RAISERROR(15250, -1, -1)
		RETURN (1)
	END

	-- Check to see the the table exists and initialize @objid.
	SELECT @objid = OBJECT_ID(@objname)

	IF @objid IS NULL
	BEGIN
		SELECT @dbname = DB_NAME()
		RAISERROR(15009, -1, -1, @objname, @dbname)
		RETURN (1)
	END

	-- OPEN CURSOR OVER INDEXES (skip stats: bug shiloh_51196)
	DECLARE ms_crs_ind CURSOR LOCAL STATIC FOR
	SELECT [indid],
		   [groupid],
		   QUOTENAME(name, N']'),
		   [status]
	FROM sysindexes
	WHERE [id] = @objid
		  AND [indid] > 0
		  AND [indid] < 255
		  AND ([status] & 64) = 0
	ORDER BY indid

	OPEN ms_crs_ind

	FETCH ms_crs_ind
	INTO @indid,
		 @groupid,
		 @indname,
		 @status

	-- IF NO INDEX, QUIT
	IF @@FETCH_STATUS < 0
	BEGIN
		DEALLOCATE ms_crs_ind
		RAISERROR(15472, -1, -1) --'Object does not have any indexes.'
		RETURN (0)
	END

	-- create temp table
	CREATE TABLE #spindtab
	(
		[index_id] INT NOT NULL,
		[index_name] sysname COLLATE DATABASE_DEFAULT NOT NULL,
		[stats] INT NULL,
		[groupname] sysname COLLATE DATABASE_DEFAULT NOT NULL,
		[index_keys] NVARCHAR(2126) COLLATE DATABASE_DEFAULT NOT NULL -- see @keys above for length descr
	)

	-- Now check out each index, figure out its type and keys and
	--	save the info in a temporary table that we'll print out at the end.
	WHILE @@FETCH_STATUS >= 0
	BEGIN
		-- First we'll figure out what the keys are.
		DECLARE @i INT,
				@thiskey NVARCHAR(131) -- 128+3

		SELECT @keys = QUOTENAME(INDEX_COL(@objname, @indid, 1), N']'),
			   @i  = 2

		IF (INDEXKEY_PROPERTY(@objid, @indid, 1, 'IsDescending') = 1)
			SELECT @keys = @keys + N'(-)'

		SELECT @thiskey = INDEX_COL(@objname, @indid, @i)

		IF (
			   (@thiskey IS NOT NULL)
			   AND (INDEXKEY_PROPERTY(@objid, @indid, @i, 'IsDescending') = 1)
		   )
			SELECT @thiskey = @thiskey + N'(-)'

		WHILE (@thiskey IS NOT NULL)
		BEGIN
			SELECT @keys = @keys + N', ' + QUOTENAME(@thiskey, N']'),
				   @i  = @i + 1

			SELECT @thiskey = INDEX_COL(@objname, @indid, @i)

			IF (
				   (@thiskey IS NOT NULL)
				   AND (INDEXKEY_PROPERTY(@objid, @indid, @i, 'IsDescending') = 1)
			   )
				SELECT @thiskey = @thiskey + N'(-)'
		END

		SELECT @groupname = groupname
		FROM sysfilegroups
		WHERE groupid = @groupid

		-- INSERT ROW FOR INDEX
		INSERT INTO #spindtab
		VALUES
		(@indid, @indname, @status, @groupname, @keys)

		-- Next index
		FETCH ms_crs_ind
		INTO @indid,
			 @groupid,
			 @indname,
			 @status
	END

	DEALLOCATE ms_crs_ind

	-- SET UP SOME CONSTANT VALUES FOR OUTPUT QUERY
	DECLARE @empty VARCHAR(1)

	SELECT @empty = ''

	DECLARE @des1 VARCHAR(35), -- 35 matches spt_values
			@des2 VARCHAR(35),
			@des4 VARCHAR(35),
			@des32 VARCHAR(35),
			@des64 VARCHAR(35),
			@des2048 VARCHAR(35),
			@des4096 VARCHAR(35),
			@des8388608 VARCHAR(35),
			@des16777216 VARCHAR(35)

	SELECT @des1 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 1

	SELECT @des2 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 2

	SELECT @des4 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 4

	SELECT @des32 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 32

	SELECT @des64 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 64

	SELECT @des2048 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 2048

	SELECT @des4096 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 4096

	SELECT @des8388608 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 8388608

	SELECT @des16777216 = [name]
	FROM master.dbo.spt_values
	WHERE [type] = 'I'
		  AND [number] = 16777216

	-- Simple workaround to establish the tree-level columns included
	DECLARE @clustered_index NVARCHAR(4000)
	DECLARE @uniquifier BIT

	SELECT @clustered_index = ISNULL(index_keys, 'RID'),
		   @uniquifier = CASE
							 WHEN index_keys IS NOT NULL
								  AND (stats & 2) = 0 THEN
								 1
							 ELSE
								 0
						 END
	FROM #spindtab
	WHERE index_id = 1

	-- DISPLAY THE RESULTS
	--(stats & 1)  0 = ignore_duplicate_keys
	--(stats & 2)  0 = unique
	--(stats & 4)  0 = ignore_duplicate_rows
	--(stats & 16)  0 = clustered
	--(stats & 32)  0 = hypothetical
	--(stats & 64)  0 statistics
	--(stats & 2048)  0 = primary_key
	--(stats & 4096)  0 = unique_key
	--(stats & 8388608)  0 = auto_create
	--(stats & 16777216)  0 = stats_no_recompute

	SELECT index_id,
		   index_name,
		   CONVERT(   VARCHAR(210), --bits 16 off, 1, 2, 16777216 on, located on group
					  CASE
						  WHEN (stats & 16)  0 THEN
							  'clustered'
						  ELSE
							  'nonclustered'
					  END + CASE
								WHEN (stats & 1)  0 THEN
									', ' + @des1
								ELSE
									@empty
							END + CASE
									  WHEN (stats & 2)  0 THEN
										  ', ' + @des2
									  ELSE
										  @empty
								  END + CASE
											WHEN (stats & 4)  0 THEN
												', ' + @des4
											ELSE
												@empty
										END + CASE
												  WHEN (stats & 64)  0 THEN
													  ', ' + @des64
												  ELSE
													  CASE
														  WHEN (stats & 32)  0 THEN
															  ', ' + @des32
														  ELSE
															  @empty
													  END
											  END + CASE
														WHEN (stats & 2048)  0 THEN
															', ' + @des2048
														ELSE
															@empty
													END + CASE
															  WHEN (stats & 4096)  0 THEN
																  ', ' + @des4096
															  ELSE
																  @empty
														  END + CASE
																	WHEN (stats & 8388608)  0 THEN
																		', ' + @des8388608
																	ELSE
																		@empty
																END + CASE
																		  WHEN (stats & 16777216)  0 THEN
																			  ', ' + @des16777216
																		  ELSE
																			  @empty
																	  END + ' located on ' + groupname
				  ) AS [index_description],
		   index_keys,
		   CASE
			   WHEN (stats & 2) = 0 /*non unique*/
					AND (stats & 16) = 0 /*non-clustered*/
					AND @uniquifier = 0 THEN
				   index_keys + ', ' + ISNULL(@clustered_index, 'RID')
			   WHEN (stats & 2) = 0 /*non unique*/
					AND (stats & 16) = 0 /*non-clustered*/
					AND @uniquifier = 1 THEN
				   index_keys + ', ' + ISNULL(@clustered_index, 'RID') + ', UNIQUIFIER'
			   WHEN (stats & 2) = 0 /*non unique*/
					AND (stats & 16)  0 /*clustered*/
		   THEN
				   index_keys + ', UNIQUIFIER'
			   WHEN @clustered_index IS NOT NULL
					AND @uniquifier = 0 THEN
				   index_keys
			   ELSE
				   index_keys + ', RID'
		   END AS [columns_in_tree],
		   CASE
			   WHEN (stats & 2048)  0 THEN
				   'All columns "included" - the leaf level IS the data row.'
			   WHEN (stats & 4096)  0 THEN
				   index_keys + ', ' + @clustered_index
			   WHEN (stats & 2) = 0 /*non unique*/
					AND (stats & 16) = 0 /*non-clustered*/
					AND @uniquifier = 0 THEN
				   index_keys + ', ' + ISNULL(@clustered_index, 'RID')
			   WHEN (stats & 2) = 0 /*non unique*/
					AND (stats & 16) = 0 /*non-clustered*/
					AND @uniquifier = 1 THEN
				   index_keys + ', ' + ISNULL(@clustered_index, 'RID') + ', UNIQUIFIER'
			   WHEN (stats & 2) = 0 /*non unique*/
					AND (stats & 16)  0 /*clustered*/
		   THEN
				   'All columns "included" - the leaf level IS the data row.'
			   WHEN (stats & 2)  0 /*unique*/
					AND (stats & 16) = 0 /*non-clustered*/
		   THEN
				   index_keys
			   ELSE
				   index_keys + ', RID'
		   END AS [columns_in_leaf]
	FROM #spindtab
	ORDER BY index_id

	DROP TABLE #spindtab

	RETURN (0) -- sp_helpindex
END
GO

EXEC sp_MS_marksystemobject 'dbo.sp_SQL2000_helpindex'
GO

Web Proxy Viewer  |  New URL  |  Original Page