Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
fizgig
Starting Member
34 Posts |
Posted - 2003-04-21 : 06:06:29
|
hi,For a current project, we have a database with no less than 90 tables. Because we ain't elephants, good database schema documentation is needed. Do you know a tool that generates sober & readable HTML documentation from an sql server database? Freeware is a plus Thanx,Fizgig |
|
|
RatTail
Crackhead
98 Posts |
Posted - 2003-04-21 : 08:54:21
|
| http://www.embarcadero.com/products/erstudio/index.asp |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-04-21 : 09:15:04
|
Hardly FREEWARE (at about US$:5,000)...What do you mean by documentation BTW? A data dictionary is almost a must for good documnetation design..there's also an ER Model (Go with VISIO for the cheapest).Here's something I wrote to publish the catalog (I did this before I knew about INFORMATION_SCHEMA. I would reccomend that you change it to use those views....Anyway, here's something:if exists (select * from sysobjects where id = object_id('dbo.sp_dba_PublishData') and sysstat & 0xf = 4) drop procedure dbo.sp_dba_PublishDataGOcreate procedure sp_dba_PublishDataas-- EXECUTE sp_dba_PublishData---- Enterprise Solutions ---- File: {}:\Technology Services\Projects\Content Management\bin\sp_dba_PublishData.SQL-- Date: March 27th, 2001-- Author: Brett Kaiser-- Server: -- Database: Any Database - Only reads sysobjects-- Login: sa-- Description: Publish a html pages for User Table Objects in the database-- Tables Used: SysObjects-- Tables Created: None---- The stream will do the following:---- 1. Create all of the Grants from the System Catalog for tables that are Prefixed with EDG-- Row Estimates:-- name rows reserved data index_size unused -- -------------------- ----------- ------------------ ------------------ ------------------ ------------------ -- ---- Change Log:-- -- User Date Description -- ------- ---------- ------------------------------------------------------------------------------- x002548 03/27/2001 Initial Implementation--declare @Name sysnamedeclare @sp_sql char(256)declare @sp_location char(256)declare @sp_path char(256)Select @sp_path = RTrim(N'E:\Christos\Pages\')Declare CRSR Cursor Static For Select RTrim(name) as Name from sysobjects Where xtype = 'U' and name like 'TBL%'Open CRSRfetch next from CRSR into @NameWhile @@fetch_status = 0Begin Select @sp_sql = RTrim(N'SELECT * FROM ' + RTrim(@Name)) Select @sp_location = RTrim(@sp_path) + RTrim(@Name) + '.htm'-- sa doesn't auth to write to the location below...and sa is required to run sp_makewebtask-- Select @sp_location = RTrim(' -- + RTrim(@Name) -- + '.htm') Select 'Tablename: ' + Rtrim(@Name) + ' is extracted with SQL: ' + RTrim(@sp_sql) + ' and is placed in location: ' + RTrim(@sp_location) EXECUTE sp_makewebtask @outputfile = @sp_location , @query = @sp_sql , @fixedfont=1 , @HTMLheader=3 , @webpagetitle=N'Microsoft SQL Server Web Assistant' , @resultstitle=N'Query Results' , @dbname=N'RealData' , @whentype=1 , @procname=N'RealData Web Page' , @codepage=65001,@charset=N'utf-8' fetch next from CRSR into @Name EndDeallocate CRSR-- Create Reference PageSelect @sp_path = RTrim(N'')Select '<LI><A HREF="' + RTrim(@sp_path) + RTrim(name) + '.htm">' + RTrim(name) + '</A>' as strLink from sysobjects Where xtype = 'U' and name like 'TBL%'Order by nameGOBrett8-)Edited by - x002548 on 04/21/2003 09:16:39Edited by - x002548 on 04/21/2003 09:17:52Edited by - x002548 on 04/21/2003 09:18:21 |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-04-21 : 09:31:44
|
| Actually that one was set up to publish data that exists in all tables. Not very appropriate for large tables I would imagine.Would be helpful for code tables I guess (nothing "transactional" though, but then again isn't everything?)You could change the sql to go against the INFORMATION_SCHEM.Columns View. Set up a cursor for every distinct table name, then generate a sql statement to pull out all the column info.That create a web page per object.But that's far from complete documentation though.You should have a textual description for every Entity, and every column at the least. I guess you could store these defs in a table and join to them as well.Good LuckBrett8-) |
 |
|
|
fizgig
Starting Member
34 Posts |
Posted - 2003-04-21 : 14:08:37
|
| thanx RatTail & Brett,The kind of documentation we want is a browsable list of all tables with al column names, types and descriptions. A good example is this freeware tool: http://dbdoc.sourceforge.net/ (check out the HTML documentation example) |
 |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2003-04-21 : 14:17:43
|
If you have added descriptions, then run this (works for SQL 2000):SET NOCOUNT ONCREATE TABLE #DataDictionary(TableName SYSNAME NOT NULL,ColumnName SYSNAME NOT NULL,Description VARCHAR(255) NOT NULL,ColumnOrder INT NOT NULL)INSERT INTO #DataDictionarySELECT o.name, c.name, CONVERT(VARCHAR(255), p.value), c.colidFROM syscolumns c, sysproperties p, sysobjects oWHERE p.smallid = c.colid AND c.id = p.id AND c.id = o.idUNIONSELECT o.name, '', CONVERT(VARCHAR(255), p.value), 0FROM sysproperties p, sysobjects oWHERE p.id = o.id AND p.smallid = 0ORDER BY 1, 4-- This is your Data Dictionary-- Export to Excel through DTSSELECT CONVERT(varchar(30), TableName) AS TableName, CONVERT(varchar(40), ColumnName) AS ColumnName, DescriptionFROM #DataDictionaryDROP TABLE #DataDictionary The above code could easily be modified to include data types and anything that you want. I wrote this code to easily see the Data Dictionary and be able to easily export it into Excel but maintain the actual dictionary in SQL Server.Maybe X002548 will add the above code to his SQL toolbox! It's something that I wrote a couple of weeks ago and works perfectly for what I need. TaraEdited by - tduggan on 04/21/2003 14:24:27 |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-04-21 : 14:19:40
|
Yes, but there's 1 column in that list that doesn't (to my knowledge) reside in the catalog.Description.That's where you have to create the data dictionary. If you create a Table Dictionary and a column Dictionary, you can join to INFORMATION_SCHEMA like I mentioned. You could then use sp_makewebtask procedure posted above and it will do the same thing.Plus I don't think it's for SQL Server:quote: The current release of this code can generate documentation for Oracle and PostgreSQL schemas
Brett8-) |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-04-21 : 14:26:15
|
| Tara, that toolbox is getting pretty full.One question though, why not use INFORMATION_SCHEMA views?Brett8-) |
 |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2003-04-21 : 14:28:27
|
| Because I haven't really looked into the INFORMATION_SCHEMA views. I probably should convert it, so maybe when I find a spare 3 minutes some day.Tara |
 |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2003-04-21 : 18:14:05
|
quote: One question though, why not use INFORMATION_SCHEMA views?
Just looked at the INFORMATION_SCHEMA and there doesn't seem to be a view that gets the description, which is the value column from the sysproperties table in my code. If I could find the description in one of those views, then this could easily be rewritten, but I don't seen it in the views. The three other columns that I use are in the views but not description.Tara |
 |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2003-04-21 : 22:44:24
|
quote: Just looked at the INFORMATION_SCHEMA and there doesn't seem to be a view that gets the description, which is the value column from the sysproperties table in my code. If I could find the description in one of those views, then this could easily be rewritten, but I don't seen it in the views. The three other columns that I use are in the views but not description.
<cranky old bastard mood, not directed at anyone>It always strikes me how people will spend/waste time designing a table and add little comments to the columns and yet forget to create a database diagram or other documentation (and to even have the NERVE to COMPLAIN about SQL Server not being able to generate this easily...ARRRRRRRRRRRRRRRRGH)Screw the descriptions! Don't design your tables using Enterprise Manager! Build them quickly in EM if you must, and if you can't invest the time in a real diagram or documentation, script them out and add comments to the script, then save it somewhere (how about source control? how useful are those descriptions anyway if your DB gets fried and you need to rebuild it?)The moral: spend time doing documentation PROPERLY, instead of using the simplest, easiest method that really doesn't help at all, and then complaining about it later. And you'll find out you don't need the documentation as often if you actually have to wrestle in the mud with the CREATE TABLE statement in query analyzer, you'll know the tables very well by the time you're done with them. And give yourself some credit, if you do 20 tables from scratch using QA/CREATE TABLE, you'll be able to do them just as fast or faster than in EM.</cranky old bastard mood, not directed at anyone> |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-04-22 : 10:04:16
|
| Whoah...Rob, you're shocked...one thing about my roots in DB2 Mainframe was that it didn't make life easy and you HAD to come up with a fundamental design (and check, and re-check it, ect).Anyway, Tara, I thought there wasn't a Description field to store in the catalog for tables, but I guess there is.exec sp_addextendedproperty N'MS_Description', N'This is the company table.', N'user', N'dbo', N'table', N'Company'And For the Column:exec sp_addextendedproperty N'MS_Description', N'The Company Name is the Key!', N'user', N'dbo', N'table', N'Company', N'column', N'Company_Name'And fn_listextendedproperty gets the properties, but it seems painful and difficult to marry to the catalog.In the past I've used Access to build a data dictionary as a repository to retain logical and physical objects. I was able to generate DDL from this, and Business users could see the definitions of Entities and Attributes. It was also helpful (because design can incorporate rather large groups of people and requirements) to distinquish inequities in the model (ie same column name in different tables with different definitions, Which can confusion, different datatypes for like things Phone Number Int or Char, ect).Anyway, Robs point(ouch that a sharp point) is extremely valuable. A good design will make a dba's life easier, and will FORCE developers to do the right thing.(I mean I've seen developers try to write sql with out even knowing the table structures, relationships, ect)Anyway, we've moved on to ERWin a couple of years ago...best thing that ever happened (They even bought a plotter).MOOBrett8-) |
 |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2003-04-22 : 12:35:06
|
| I hope Rob's point was not even slightly directed at me (even though it says not directed at anyone) because I follow all of what he said. We not only create the data dictionary but we also create the database diagram. The code that I gave can be used if you have created your data dictionary using the description property of the table. I do not use Enterprise Manager to design my tables and I always try to get the developers to do the same. Anyway, hopefully other people will follow robvolk's advice since he is very correct.Tara |
 |
|
|
X002548
Not Just a Number
15586 Posts |
Posted - 2003-04-22 : 13:30:43
|
Tara,I really don't think Rob was singling anyone out (how would he know anyway).And anyway, if fizgig is still around, I (FINALLY) fixed the code that will allow anyone to create html documentation for a data dictionary (only part of the required documentation, rob) in the existing database. I guess you could even leverage it for User Help.The last statement copys the data off the server to a file server. I've included sample descriptions (good lord I've got a lot to do in my real db). This should all work top to bottom if it's cut and paste, don't forget to supply a valid UNC for the file to be copied.USE NorthwindGoif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[DICT_TABLE]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)drop table [dbo].[DICT_TABLE]GOCREATE TABLE DICT_TABLE (TABLE_NAME sysname NOT NULL, Description varchar(4000))GOINSERT INTO DICT_TABLE (TABLE_NAME, Description)SELECT TABLE_NAME, Convert(varchar(4000),' ') As Description FROM INFORMATION_SCHEMA.Tables WHERE TABLE_TYPE = 'BASE TABLE'ORDER BY TABLE_NAMEGOif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[DICT_COLUMN]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)drop table [dbo].[DICT_COLUMN]GOCREATE TABLE DICT_COLUMN (TABLE_NAME sysname NOT NULL, COLUMN_NAME sysname NOT NULL, Description varchar(4000))GOINSERT INTO DICT_COLUMN (TABLE_NAME, COLUMN_NAME, Description)SELECT TABLE_NAME, COLUMN_NAME, Convert(varchar(4000),' ') As Description FROM INFORMATION_SCHEMA.Columns oWHERE EXISTS ( SELECT 1 FROM DICT_TABLE i WHERE o.TABLE_NAME = i.TABLE_NAME)ORDER BY TABLE_NAMEGOUPDATE DICT_TABLE SET Description = 'Contains a list of all types of Descriptiveclassifications that products may belong to. Contains a list of all types of Descriptiveclassifications that products may belong to. Contains a list of all types of Descriptiveclassifications that products may belong to.'WHERE TABLE_NAME = 'Categories'GOUPDATE DICT_COLUMN SET Description = 'This is the key to the table and is an icremental value starting with 1'WHERE TABLE_NAME = 'Categories' AND COLUMN_NAME = 'CategoryID'GOif exists (select * from sysobjects where id = object_id('dbo.isp_dba_PublishDictionary') and sysstat & 0xf = 4) drop procedure dbo.isp_dba_PublishDictionaryGOCREATE PROCEDURE isp_dba_PublishDictionary @dbnameIN sysname, @sp_path varchar(256)ASDECLARE @TABLE_NAME sysname, @sp_sql varchar(4000), @sp_location varchar(256), @Description varchar(4000) , @WebPageTitleIN varchar(80), @resultstitleIN varchar(80), @ProcNameIN varchar(255)DECLARE CRSR CURSOR STATIC FOR SELECT l.TABLE_NAME , r.Description FROM INFORMATION_SCHEMA.Tables l LEFT JOIN DICT_TABLE r ON l.TABLE_NAME = r.TABLE_NAME WHERE l.TABLE_TYPE = 'BASE TABLE' OPEN CRSRFETCH NEXT FROM CRSR into @TABLE_NAME, @DescriptionWHILE @@fetch_status = 0 BEGIN SELECT @sp_sql = 'SELECT l.TABLE_NAME, r.Description' + ' FROM INFORMATION_SCHEMA.Tables l' + ' LEFT JOIN DICT_TABLE r' + ' ON l.TABLE_NAME = r.TABLE_NAME' + ' WHERE l.TABLE_NAME =' + '''' + RTrim(@TABLE_NAME) + '''' + ' ' + 'SELECT ' + ' l.COLUMN_NAME, l.DATA_TYPE, l.IS_NULLABLE, r.description' + ' FROM INFORMATION_SCHEMA.Columns l' + ' LEFT JOIN DICT_COLUMN r' + ' ON l.TABLE_NAME = r.TABLE_NAME' + ' AND l.COLUMN_NAME = r.COLUMN_NAME' + ' WHERE l.TABLE_NAME =' + '''' + RTrim(@TABLE_NAME) + '''' + ' ORDER BY ORDINAL_POSITION' , @sp_location = @sp_path + @TABLE_NAME + '.htm' , @WebPageTitleIN = 'Data Dictionary for '+ @DBNameIN , @resultstitleIN = Left((@TABLE_NAME + ':' + @Description), 255) , @procNameIN = 'wbtsk_'+@TABLE_NAME SELECT 'Tablename: ' + Rtrim(@TABLE_NAME) + ' is extracted with SQL: ' + RTrim(@sp_sql) + ' and is placed in location: ' + RTrim(@sp_location) EXECUTE sp_makewebtask @outputfile = @sp_location , @query = @sp_sql , @fixedfont=1 , @HTMLheader=3 , @webpagetitle=@WebPageTitleIN , @resultstitle=@resultstitleIN , @dbname=@dbNameIN , @whentype=1 , @procname=@procnameIN , @codepage=65001,@charset=N'utf-8' FETCH NEXT FROM CRSR INTO @TABLE_NAME, @Description ENDCLOSE CRSRDEALLOCATE CRSRGOmaster..xp_cmdshell 'MD C:\TEMP\DICT\'GOEXEC isp_dba_PublishDictionary 'Northwind','C:\TEMP\DICT\'GOmaster..xp_cmdshell 'DIR C:\TEMP\DICT\*.*'GOmaster..xp_cmdshell 'COPY C:\TEMP\DICT\*.* \\UNC filename\*.*'GOBrett8-)Edited by - x002548 on 04/22/2003 13:32:02Edited by - x002548 on 04/22/2003 13:34:12 |
 |
|
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2003-04-22 : 14:12:26
|
| Yeah I know, I just wanted to make it clear that I am not one of those lazy DBAs who does not document the databases that he/she supports. I respect robvolks' opinion (very highly too), but I just didn't want anyone to have the impression that I was one of those people that he was mentioning.Tara |
 |
|
|
fizgig
Starting Member
34 Posts |
Posted - 2003-04-22 : 16:53:38
|
| X002548,Thanx for the interesting script. I will give it a try tomorrow.With kind regards,Fizgig |
 |
|
|
robvolk
Most Valuable Yak
15732 Posts |
Posted - 2003-04-22 : 21:31:03
|
Nope, I wasn't aiming at anyone, it's just a thing I've noticed OTHER database designers do. I'm guilty of it myself when I used Access, luckily nothing big enough that I couldn't figure it out later. But man, I've seen WAY too many Access DB's with 150+ tables and no documentation at all except for column descriptions, and even those were useless. Even the built-in documentor feature couldn't make sense of them.And yes, if you're an ErWin or Visio or other modeling/diagramming tool user, you're a step (probably two steps) ahead of me. I haven't been using those kinds of things enough, so if you ever feel I'm picking on you, just throw that back in my face. |
 |
|
|
nr
SQLTeam MVY
12543 Posts |
Posted - 2003-04-22 : 22:08:48
|
| I like ErWin but don't try to use it too early on in the design.I start off with design decisions and descriptions of relationships in text.How the business entities map to the physical model and descriptions of any fields that aren't obvious.Ok, I do this because I have a terrible memory and also so people aren't stuck if I oversleep, but it does end up with a useful document.Trying to diagram the database too early in two much detail can end up as a huge overhead - and you can end up sticking to bad decisions because of the effort needed to update the diagrams (I've heard that as an excuse a few times).Also stay clear of trying to use a diagramming tool to update the database - or even a setup that can.==========================================Cursors are useful if you don't know sql.DTS can be used in a similar way.Beer is not cold and it isn't fizzy.Edited by - nr on 04/22/2003 22:09:44 |
 |
|
|
|
|
|
|
|