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.

 All Forums
 SQL Server 2000 Forums
 SQL Server Development (2000)
 Finding maximum required field size

Author  Topic 

samtoffa
Yak Posting Veteran

60 Posts

Posted - 2004-07-15 : 19:03:32
I have inherited a number of badly-designed databases that need to be ported to SQL server. Typically there is a field called Firstname char(500) but the longest data item stored in this field is no more than 12 characters. There are dozens of fields and 3.5-4 million rows in the various tables. Is there a simple way to find the maximum size of a piece of text held in each field in a table (my instinct is to write a procedure that uses the len(string) function and iterates through every field but this doesn’t seem like a very elegant solution)?

kselvia
Aged Yak Warrior

526 Posts

Posted - 2004-07-15 : 22:48:27
Len() is the only way I know of to find actual space used in columns.

I had this and made a few changes to adapt it to your problem. It's not very elegant but you only need to run it once.
Change Pubs to your DB in three places below



USE pubs

Create Procedure p_CheckSizes (@TableName sysname)
AS
BEGIN
SET NOCOUNT ON
SET CONCAT_NULL_YIELDS_NULL OFF

IF Object_ID('v_CheckSizes') IS Not Null
DROP VIEW v_CheckSizes

IF Object_ID('tempdb..##exec') IS Not Null
DROP TABLE ##exec

SELECT ID = Identity(int, 1,1),
Cmd = Cast ('Create View v_CheckSizes AS ' AS Varchar(255))
INTO ##exec

INSERT ##exec
SELECT 'Select ''L'' Type, Max(Len(['+COLUMN_NAME+'])) MaxLen, ''['+COLUMN_NAME+']'' ColName FROM ['+TABLE_NAME+'] UNION ALL ' Cmd
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TableName AND DATA_TYPE in ( 'varchar', 'nvarchar')

INSERT ##exec
SELECT 'Select ''D'' Type, '+Cast(CHARACTER_MAXIMUM_LENGTH as Varchar)+' MaxLen, ''['+COLUMN_NAME+']'' ColName UNION ALL ' Cmd
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TableName AND DATA_TYPE in ( 'varchar', 'nvarchar' )

INSERT ##exec (cmd) SELECT 'SELECT ''#'',0, ''#['+@TableName+']#'''

If (Select count(1) From ##exec) > 2
BEGIN
EXEC master..xp_execresultset N'SELECT ''''+Cmd+'''' FROM ##exec ORDER BY ID ',N'Pubs'

DROP TABLE ##exec

Select 'Unused Space ['+@TableName+'] ' + D.ColName + ' --> ' + Cast (D.MaxLen - L.MaxLen As Varchar(10)) [Unused Space In Column]
FROM v_CheckSizes L, v_CheckSizes D
WHERE L.ColName = D.ColName
AND D.MaxLen <> L.MaxLen
AND D.Type = 'D'
AND L.Type = 'L'
AND L.ColName <> '#['+@TableName+']#'
ORDER BY ( D.MaxLen - L.MaxLen )
END

END

Run:

master..xp_execresultset 'SELECT ''exec p_CheckSizes ''''''+TABLE_NAME+'''''''' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = ''BASE TABLE''',N'Pubs'

To generate output similar to:

Unused Space [stores] [stor_name] --> 4
Unused Space [stores] [city] --> 11
Unused Space [stores] [stor_address] --> 21
Unused Space [titles] [title] --> 17
Unused Space [titles] [notes] --> 21


--Ken
Your Kung-Fu is not strong. -- 'The Core'
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2004-07-16 : 01:25:28
Similar, but this is what I use for checking Max Length of columns, and how many are "used" (not null)

It generates a script which needs to then be run, so set Query Analysers to TEXT RESULTS mode (Control-T) before running

SELECT [-- Use this query to produce a column list with a count of the number of rows (where used)]
= CASE WHEN colid = 1 THEN '' ELSE 'UNION ALL ' END
+ 'SELECT [Used]=COALESCE((SELECT SUM(CASE WHEN ['
+ C.name + '] IS NULL THEN 0 ELSE 1 END) FROM [' + O.name + ']), 0), '
+ '[' + O.name + ']=''' + C.name + ''''
FROM dbo.syscolumns C
JOIN dbo.sysobjects O
ON O.id = C.id
AND O.type = 'U'
WHERE O.name NOT IN ('dtproperties')
-- AND O.name = 'MyTable'
ORDER BY O.name, colid

SELECT [-- Use this query to produce a column list with Max Length of the data in that column]
= CASE WHEN colid = 1 THEN '' ELSE 'UNION ALL ' END
+ 'SELECT [MaxLen]=COALESCE((SELECT MAX(DATALENGTH(['
+ C.name + '])) FROM [' + O.name + ']), 0), '
+ '[' + O.name + ']=''' + C.name + ''''
FROM dbo.syscolumns C
JOIN dbo.sysobjects O
ON O.id = C.id
AND O.type = 'U'
WHERE O.name NOT IN ('dtproperties')
-- AND O.name = 'MyTable'
ORDER BY O.name, colid

Kristen
Go to Top of Page

samtoffa
Yak Posting Veteran

60 Posts

Posted - 2004-07-16 : 06:26:04
Thanks guys, your solutions are much more sophisticated than anything that I've tried. This is just the sort of thing that I know myself and others will need to do again in the future so thanks for the help.
Cheers,
Sam
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2004-07-16 : 08:41:33
My pleasure
Go to Top of Page
   

- Advertisement -