Important alert: (current site time 7/15/2013 7:01:43 PM EDT)
 

VB icon

Integrated database documentation using stored procedure

Email
Submitted on: 6/12/2003 1:54:21 PM
By: Christina McEntire 
Level: Advanced
User Rating: By 17 Users
Compatibility: SQL Server 2000, SQL Server 7.0
Views: 25501
author picture
(About the author)
 
     This stored procedure will help you to document your database within the database. It creates/updates a table that lists all of the user tables, views and stored procedures in the database, as well as all of the views and stored procedures that reference each of those objects. There are custom fields for putting in the purpose of the object, notes, or anything else you want to document. Executing the procedure after the initial creation will: 1) update the names of the objects, if changed; 2) add new objects; 3) update the list of views and stored procedures referencing the objects; and 4) mark any objects that have been deleted. This is a great way to keep your documentation up to date, in a place where all of the database developers can find it! (Updated 06/18/2003 -- see notes in code below.)
 
code:
Can't Copy and Paste this?
Click here for a copy-and-paste friendly version of this code!
 
Terms of Agreement:   
By using this code, you agree to the following terms...   
  1. You may use this code in your own programs (and may compile it into a program and distribute it in compiled format for languages that allow it) freely and with no charge.
  2. You MAY NOT redistribute this code (for example to a web site) without written permission from the original author. Failure to do so is a violation of copyright laws.   
  3. You may link to this code from another website, but ONLY if it is not wrapped in a frame. 
  4. You will abide by any additional copyright restrictions which the author may have placed in the code or code's description.
				
--**************************************
-- Name: Integrated database documentation using stored procedure
-- Description:This stored procedure will help you to document your database within the database. It creates/updates a table that lists all of the user tables, views and stored procedures in the database, as well as all of the views and stored procedures that reference each of those objects. There are custom fields for putting in the purpose of the object, notes, or anything else you want to document. Executing the procedure after the initial creation will: 1) update the names of the objects, if changed; 2) add new objects; 3) update the list of views and stored procedures referencing the objects; and 4) mark any objects that have been deleted. This is a great way to keep your documentation up to date, in a place where all of the database developers can find it! (Updated 06/18/2003 -- see notes in code below.)
-- By: Christina McEntire
--
-- Returns:Creates/updates a table in your database called INFO_DbObjects to store the information generated by this procedure plus any other documentation you want to add.
--
--This code is copyrighted and has-- limited warranties.Please see http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=699&lngWId=5--for details.--**************************************

/******************************************************************************
** Name: pr_InfoDbObjects
** Description: Set up and maintain tables in order to keep track of database structure, including user tables, stored procedures, and views
**	 Initially:
**		-- create a table to hold the info, and populate it with the object names
**		-- populate list of all stored procedures and views that reference each object
**	Update:
**		-- add new objects to the table
**		-- update object names where they've changed
** 		-- mark deleted objects as deleted
**		-- update lists of stored procedures and views that reference each object
** Inputs: None
** Results: This procedure creates/updates a table in your database called INFO_DbObjects to store the information generated by this procedure plus
**		any other documentation you want to add.
** Additional Note: The Sys Id for a table changes if the order of the columns in changed, i.e. column dragged to different position; 
** 	for this reason, we need to check for table updates on both changed SysId and changed TableName
** Other: -- To see tables, stored procedures and views separately, just set up a view for each type
**	 -- If the database is changing over time, can set up a job to run this regularly. It will keep all the database object names up-to-date, 
**		as well as the list of views and stored procedures referencing each object. Any custom-documention fields will remain untouched
**		by running this procedure
** Updated 06/17/2003 — New addition for marking objects as not deleted if they had been deleted and then re-added later. Also, error in logic updated.
** Updated 06/18/2003 to correct references to an incorrect object name introduced with the last update.
*******************************************************************************/
CREATE PROCEDURE dbo.pr_InfoDbObjects
			 @Print bit = 0	-- ** flag for whether or not to print rows. Printing is off unless specifically passed in as true (1)
AS
SET NOCOUNT ON
DECLARE	 @ObjectName	varchar(100)
		, @RefView 	varchar(100)
		, @RefProc	varchar(100)
		, @AllViews	varchar(500)
		, @AllProc	varchar(500)
		, @RowCount	int
PRINT 'Beginning update of database documentation'
--------------------------------------------------------------------------------------------------------
-- ** If table doesn't exist, create it
IF NOT EXISTS (select * from sysobjects where id = object_id(N'[dbo].[INFO_DbObjects]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
BEGIN
	PRINT ''
	PRINT 'Creating table to document database structure'
	CREATE TABLE [dbo].[INFO_DbObjects] (
		[SysId] [int] NOT NULL ,
		[ObjectName] [varchar] (50) NOT NULL ,	-- ** "U" is table, "V" is view, "P" is stored procedure
		[ObjectType] [char] (1) NOT NULL ,
		[Purpose] [varchar] (300) NULL ,		-- ** custom -- YOUR documentation
		[Notes] [varchar] (1000) NULL ,		-- ** custom -- YOUR documentation
		[RefByViews] [varchar] (500) NULL ,
		[RefByProc] [varchar] (500) NULL ,
		[RefByOther_Manual] [varchar] (300) NULL ,	-- ** custom -- use to keep track of scheduled jobs or DTS packages that reference the object (manually updated) 
		[ObjectDeletedYN] [bit] NOT NULL CONSTRAINT [DF_INFO_DbObjects_ObjectDeletedYN] DEFAULT (0) ,
		[InsertDate] [smalldatetime] NOT NULL CONSTRAINT [DF_INFO_DbObjects_InsertDate] DEFAULT (getdate()) ,
	CONSTRAINT [PK_INFO_DbObjects] PRIMARY KEY NONCLUSTERED 
	(
		[SysId]
	) WITH FILLFACTOR = 90 ON [PRIMARY] 
	) ON [PRIMARY]
END
---------------------------------------------------
ELSE	
-- ** table already exists; check for updates
BEGIN
	-- ** Determine if any of the object names or sys id's have changed
	IF EXISTS(SELECT * FROM INFO_DbObjects O INNER JOIN sysobjects SO ON O.SysId = SO.id
				WHERE O.ObjectName <> SO.name)
			OR EXISTS(SELECT * FROM INFO_DbObjects O INNER JOIN sysobjects SO ON O.ObjectName = SO.name
				WHERE O.SysId <> SO.id)
	BEGIN
		-- ** Update INFO_DbObjects with object names for those that have changed BASED ON SAME SYSID
		UPDATE O
		SET O.ObjectName = SO.name
		FROM INFO_DbObjects O
			INNER JOIN sysobjects SO
				ON O.SysId = SO.id
		WHERE O.ObjectName <> SO.name
		SELECT @RowCount = @@RowCount
		IF @RowCount > 0 
		BEGIN
			PRINT ''
			PRINT 'Updated INFO_DbObjects with changed database object names based on same SysId'
		PRINT Convert(varchar(4), @RowCount) + ' row(s) affected'
		END
		---------------------------------------------------
		-- ** Update INFO_DbObjects with sys id's for those that have changed BASED ON SAME NAME (and object type must match as well)
	
		UPDATE O
		SET O.SysId = SO.id
		FROM INFO_DbObjects O INNER JOIN sysobjects SO
			ON O.ObjectName = SO.name
				AND O.ObjectType = SO.type
		WHERE O.SysId <> SO.id
		SELECT @RowCount = @@RowCount
		IF @RowCount > 0 
		BEGIN
			PRINT ''
			PRINT 'Updated INFO_DbObjects with changed SysId based on same object name and type'
		PRINT Convert(varchar(4), @RowCount) + ' row(s) affected'
		END
	END
	---------------------------------------------------
	-- ** Mark objects as NOT deleted if they HAD been marked as deleted but now exist...
	UPDATE O
	SET	O.ObjectDeletedYN = 0
	FROM INFO_DbObjects O 
		INNER JOIN sysobjects SO 
			ON O.SysId = SO.id
	WHERE O.ObjectDeletedYN = 1
	SELECT @RowCount = @@RowCount
	IF @RowCount > 0 
	BEGIN
		PRINT ''
		PRINT 'Marked un-deleted objects as NOT deleted'
		PRINT Convert(varchar(4), @RowCount) + ' row(s) affected'
	END
	---------------------------------------------------
	-- ** Mark objects as deleted if no match (both SysId and ObjectName have been updated, so no match on SysId should cover it)
	-- ** DO NOT actually DELETE the record from the table -- the user may have info in the custom columns they don't want to lose
	UPDATE O
	SET	O.ObjectDeletedYN = 1
	FROM INFO_DbObjects O 
		LEFT OUTER JOIN sysobjects SO 
			ON O.SysId = SO.id
	WHERE SO.Id is null AND O.ObjectDeletedYN = 0
	SELECT @RowCount = @@RowCount
	IF @RowCount > 0 
	BEGIN
		PRINT ''
		PRINT 'Marked deleted objects as deleted'
		PRINT Convert(varchar(4), @RowCount) + ' row(s) affected'
	END
END
--------------------------------------------------------------------------------------------------------
-- ** Insert new object names
BEGIN
	INSERT INTO INFO_DbObjects(SysId, ObjectName, ObjectType)
	SELECT Distinct 	 SO.id
				, SO.Name
				, SO.type
	FROM sysobjects SO 
		LEFT OUTER JOIN INFO_DbObjects O
			ON SO.id = O.SysId
	WHERE
		((SO.type = 'u'
		AND SO.Name NOT LIKE 'INFO[_]%')	-- ** (database "Info" table created by this procedure) 
			OR (SO.type = 'p')
			OR (SO.type = 'v')
		)
		AND SO.Category <> 2	-- ** rules out system objects
		AND SO.name <> 'dtproperties'
		AND O.SysId is null	-- ** object not yet in our table
		-- ** ADD any other custom criteria for other objects you want to include or exclude...
	ORDER BY SO.type, SO.Name
	SELECT @RowCount = @@RowCount
	IF @RowCount > 0 
	BEGIN
		PRINT ''
		PRINT 'Inserting names of new objects'
		PRINT Convert(varchar(4), @RowCount) + ' row(s) affected'
	END
END
------------------------------------------------------------------------------------------------------------------
-- ** Find all views and procedures that reference each object
BEGIN
		-- ** NOTE: We're using the "referenced by" rather than using sp_depends -- this is more accurate because it will also include objects referenced
		-- ** 	in stored procedures where an EXEC(@Statement) or similar is used, where the SQL string is built piece by piece, etc.
	PRINT ''
	PRINT 'Beginning update of views and procedures that reference each object'
	-- ** initialize @AllViews & @AllProc as empty, not null
	SELECT @AllViews = ''	
		, @AllProc = ''
	
	-- ** get the first object name from INFO_DbObjects
	SELECT @ObjectName = MIN(ObjectName) FROM INFO_DbObjects WHERE ObjectDeletedYN = 0
	
	WHILE @ObjectName is not null
	BEGIN
		-- ** Find Views that reference each table
		SELECT @RefView = MIN(so.name) 
			FROM sysobjects so INNER JOIN syscomments sc ON so.id = sc.id 
			WHERE so.type = 'V' AND sc.text LIKE '%' + @ObjectName + '%'
				AND so.name <> @ObjectName
	
		WHILE @RefView is not null
		BEGIN
			SELECT @AllViews = @AllViews + @RefView + '; '
	
			-- ** go get the next view that references it
			SELECT @RefView = MIN(so.name) 
				FROM sysobjects so INNER JOIN syscomments sc ON so.id = sc.id 
				WHERE so.type = 'V' AND sc.text LIKE '%' + @ObjectName + '%'
					AND so.name <> @ObjectName
					AND so.name > @RefView
		END
	
		-- ** Find Stored Procedures that reference each table
		SELECT @RefProc = MIN(so.name) 
			FROM sysobjects so INNER JOIN syscomments sc ON so.id = sc.id 
			WHERE so.type = 'P' AND sc.text LIKE '%' + @ObjectName + '%'
				AND so.name <> @ObjectName
	
		WHILE @RefProc is not null
		BEGIN
			SELECT @AllProc = @AllProc + @RefProc + '; '
			-- ** go get the next procedure that references it
	
			SELECT @RefProc = MIN(so.name) 
				FROM sysobjects so INNER JOIN syscomments sc ON so.id = sc.id 
				WHERE so.type = 'P' AND sc.text LIKE '%' + @ObjectName + '%'
					AND so.name <> @ObjectName
					AND so.name > @RefProc
		END
		-- ** trim final semicolon & space from @AllViews and @AllProc
		IF @AllViews LIKE '%;%'
		BEGIN
	
			SELECT @AllViews = Substring(@AllViews, 1, Len(@AllViews) - 1)
		END
	
		IF @AllProc LIKE '%;%'
		BEGIN
			-- ** trim off the last semicolon & space
			SELECT @AllProc = Substring(@AllProc, 1, Len(@AllProc) - 1)
		END
		-- ** Update the Info Table with the list of views and stored procedures that reference the table; 
		-- ** 	update ONLY if the information is different than what's already there...
		IF EXISTS(SELECT * FROM INFO_DbObjects
				WHERE ObjectName = @ObjectName AND (RefByViews <> @AllViews OR RefByProc <> @AllProc))
		BEGIN
			PRINT ''
			PRINT '	Object Name: ' + @ObjectName
			PRINT '		Views: ' + @AllViews
			PRINT '		Procedures: ' + @AllProc
			UPDATE INFO_DbObjects
			SET 	 RefByViews = @AllViews
				, RefByProc = @AllProc
			WHERE ObjectName = @ObjectName
		END
		-- ** reset @AllViews and @AllProc
		SELECT @AllViews = ''
			, @AllProc = ''
		-- ** get the next table from Info Tables
		SELECT @ObjectName = MIN(ObjectName) FROM INFO_DbObjects WHERE ObjectDeletedYN = 0 AND ObjectName > @ObjectName
	END
END
PRINT ''
PRINT 'Update of database documentation completed'
GO


Report Bad Submission
Use this form to tell us if this entry should be deleted (i.e contains no code, is a virus, etc.).
This submission should be removed because:

Your Vote

What do you think of this code (in the Advanced category)?
(The code with your highest vote will win this month's coding contest!)
Excellent  Good  Average  Below Average  Poor (See voting log ...)
 

Other User Comments
6/13/2003 2:54:54 AMMark Buckley

Awesome stuff Christina, worked right out of the box. I'm going to start using this procedure with all my databases right away. Thanks for the great code. -MARK-
(If this comment was disrespectful, please report it.)

 
6/15/2003 2:00:14 PMsbguy

Great code, Christina. My only question is how does it determine if a view, for instance, is referenced by another view or a proc. I have many cases like that, but nothing is showing up in the referenced by columns.
(If this comment was disrespectful, please report it.)

 
6/16/2003 9:31:22 AMChristina McEntire

Christina’s response to above comment: The code looks at the column called “text” in the syscomments table. This is where the actual code for the view or procedure is stored, i.e., the “CREATE VIEW vwXXX AS…”, which holds the complete text for the view or stored procedure. Unfortunately, I cannot duplicate the problem. You might want to check the following: Have you dragged the columns in the table so that they’re bigger and show multiple lines? (Object names are separated by a semi-colon & space, but if your column is small, you may only see the first procedure/view in the list, not all of them.) Are the objects you’re referring to in a different database? This code is written to only look through objects in the current database. Christina
(If this comment was disrespectful, please report it.)

 
6/16/2003 9:35:21 AM

Awesome code, thanks very much!
(If this comment was disrespectful, please report it.)

 
6/16/2003 9:50:32 AMJim Black

WOW! Great code. This will help with my database documentation.
(If this comment was disrespectful, please report it.)

 
8/27/2003 12:46:29 PMAmazing

Excellent work
Keep up the good work
(If this comment was disrespectful, please report it.)

 
11/21/2005 5:51:26 AMVishwanath

Ohh!! Great code. Looking for more than 5 points to vote you.. Thanx for sharing
(If this comment was disrespectful, please report it.)

 
12/14/2005 6:46:58 AMAmal

Very useful piece of code for:
You da groovey chic
AGreat example of Paste n Play
(If this comment was disrespectful, please report it.)

 

Add Your Feedback
Your feedback will be posted below and an email sent to the author. Please remember that the author was kind enough to share this with you, so any criticisms must be stated politely, or they will be deleted. (For feedback not related to this particular code, please click here instead.)
 

To post feedback, first please login.