Reputation: 11182
Because I want to convert the columns to not be varchar(MAX)
I want to see the maximum datalength for each column to decide what the new size should be.
I have this query for finding all my (n)varchar(MAX)
columns.
SELECT [TABLE_NAME], [COLUMN_NAME]
FROM information_schema.columns
WHERE DATA_TYPE IN ('varchar', 'nvarchar')
AND CHARACTER_MAXIMUM_LENGTH = -1
ORDER BY TABLE_NAME, COLUMN_NAME
For instance I have a customer table and among the results the following is output for my customers table
+------------+--------------+
| TABLE_NAME | COLUMN_NAME |
+------------+--------------+
| customers | name |
| customers | address |
| customers | postal_code |
| customers | city |
| customers | email |
| customers | phone_number |
+------------+--------------+
By running the following queries:
SELECT MAX(DATALENGTH(name)) FROM customers
SELECT MAX(DATALENGTH(address)) FROM customers
SELECT MAX(DATALENGTH(postal_code)) FROM customers
SELECT MAX(DATALENGTH(city)) FROM customers
SELECT MAX(DATALENGTH(email)) FROM customers
SELECT MAX(DATALENGTH(phone_number)) FROM customers
I can get the result I want, but I'd really like for it to be just one query returning something like:
+------------+--------------+------------+
| TABLE_NAME | COLUMN_NAME | Datalength |
+------------+--------------+------------+
| customers | name | 93 |
| customers | address | 122 |
| customers | postal_code | 6 |
| customers | city | 44 |
| customers | email | 75 |
| customers | phone_number | 18 |
+------------+--------------+------------+
I have tried
SELECT
[TABLE_NAME], [COLUMN_NAME],
(SELECT MAX(DATALENGTH(COLUMN_NAME))
FROM TABLE_NAME) AS 'MaxContentLength'
FROM information_schema.columns
WHERE DATA_TYPE IN ('varchar', 'nvarchar')
AND CHARACTER_MAXIMUM_LENGTH = -1
ORDER BY TABLE_NAME, COLUMN_NAME
But I get this error:
Msg 208, Level 16, State 1, line 1
Invalid object name 'TABLE_NAME'
How do I fix this issue (or is there another way to do what I want?)
Upvotes: 2
Views: 1729
Reputation: 351
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, DATALENGTH(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE DATA_TYPE IN ('VARCHAR', 'NVARCHAR', 'CHAR', 'NCHAR') AND CHARACTER_MAXIMUM_LENGTH < DATALENGTH(COLUMN_NAME)
Upvotes: 0
Reputation: 483
This is my approach to solve your question, maybe not the fastest one.
declare @tbl varchar(128), @fld varchar(128)
declare @res table (
[Table_Name] varchar(128), [Column_Name] varchar(128), [DataLength] int)
declare c1 cursor local for
select c.TABLE_NAME, c.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS c
join INFORMATION_SCHEMA.TABLES t on
(t.TABLE_CATALOG = c.TABLE_CATALOG and
t.TABLE_SCHEMA = c.TABLE_SCHEMA and
t.TABLE_NAME = c.TABLE_NAME)
where t.TABLE_TYPE <> 'VIEW'
and c.DATA_TYPE in ('varchar', 'nvarchar')
and c.CHARACTER_MAXIMUM_LENGTH = -1
open c1
fetch next from c1 into @tbl, @fld
while @@FETCH_STATUS=0
begin
insert into @res
exec ('select '''
+@tbl+''' as [TABLE_NAME], '''
+@fld+''' as [COLUMN_NAME], max(datalength('
+@fld+')) as [DataLength] from '
+@tbl)
fetch next from c1 into @tbl, @fld
end
close c1
deallocate c1
select * from @res
Upvotes: 2
Reputation: 29677
Those multiple queries that use DATALENGTH can be combined in one.
untested notepad scribble
SELECT
[TABLE_NAME],
[COLUMN_NAME],
[Datalength]
FROM
(
SELECT
'customers' AS [TABLE_NAME],
MAX(DATALENGTH(name)) AS name,
MAX(DATALENGTH(address)) AS address,
MAX(DATALENGTH(postal_code)) AS postal_code,
MAX(DATALENGTH(city)) AS city,
MAX(DATALENGTH(email)) AS email,
MAX(DATALENGTH(phone_number)) AS phone_number
FROM customers
) AS src
UNPIVOT
(
[Datalength]
FOR [COLUMN_NAME] IN
([name], [address], [postal_code], [city], [email], [phone_number])
) AS unpvt;
Upvotes: 0
Reputation: 1305
Is this correct for you ?
SELECT
I.TABLE_NAME, I.COLUMN_NAME,
(SELECT MAX(DATALENGTH(COLUMN_NAME))
FROM information_schema.columns
WHERE TABLE_NAME = I.TABLE_NAME) AS 'MaxContentLength'
FROM information_schema.columns AS I
WHERE I.DATA_TYPE IN ('varchar', 'nvarchar')
AND CHARACTER_MAXIMUM_LENGTH = -1
ORDER BY I.TABLE_NAME, I.COLUMN_NAME
Upvotes: 0