我们的应用程序使用一系列包含许多varchar(1000)列的表。在系统开发期间,这被认为是用户输入文本的足够空间。但是,现在我们遇到了文本被切断的问题,所以看起来有些用户正在输入更多可以容纳的文本。但是,我认为这些字段的滥用行为猖獗,我想看看哪些列正在使用。
从SO上回答的另一个问题,我提出了以下查询来提取表中varchar列的名称:
select
syscolumns.name as [Column],
syscolumns.length as [MaxLength]
from
sysobjects, syscolumns
where sysobjects.id = syscolumns.id
and sysobjects.xtype = 'u'
and sysobjects.name = 'TableWithTooManyVarcharColumns'
and syscolumns.xusertype = 167
但现在我想在新查询中使用这些列的名称,并计算
SELECT
[Column] as [Name],
[MaxLength],
MAX(LEN([Column])) as [MaxUsedLength],
AVG(LEN([Column])) as [AvgUsedLength],
STDEV(LEN([Column])) as [StdDev]
FROM TableWithTooManyVarcharColumns
INNER JOIN **{{ reference to table from query above }}**
当然,第一个查询返回列的名称,而第二个查询需要对列的引用,所以我不确定如何正确组合它们。任何SQL Server大师都能提供帮助吗?
答案 0 :(得分:4)
连接两个派生表或使用CTE。顺便说一下,您正在为模式引用使用一些过时的术语
select
DefinedName = sysdef.name,
Columnname = tbl.name,
DefinedLength = sysdef.max_length,
etc ...
from (
select c.name, c.max_length
from sys.columns c
join sys.tables t
on c.object_id = t.object_id
where t.name = 'TableWithTooManyVarcharColumns'
) sysdef
join (
SELECT
[Column] as [Name],
[MaxLength],
MAX(LEN([Column])) as [MaxUsedLength],
AVG(LEN([Column])) as [AvgUsedLength],
STDEV(LEN([Column])) as [StdDev]
FROM TableWithTooManyVarcharColumns
) tbl
on sysdef.name = tbl.name
或强>
;WITH sysdef AS (
select c.name, c.max_length
from sys.columns c
join sys.tables t
on c.object_id = t.object_id
where t.name = 'TableWithTooManyVarcharColumns'
),
tbl AS (
SELECT
[Column] as [Name],
[MaxLength],
MAX(LEN([Column])) as [MaxUsedLength],
AVG(LEN([Column])) as [AvgUsedLength],
STDEV(LEN([Column])) as [StdDev]
FROM TableWithTooManyVarcharColumns
)
select
DefinedName = sysdef.name,
Columnname = tbl.name,
DefinedLength = sysdef.max_length,
etc ...
from tbl t
join sysdef d
on tbl.name = d.name
修改强>
declare @sql nvarchar(4000)
declare @colname nvarchar(100)
declare @max_length nvarchar(15)
declare c cursor for
select c.name, c.max_length
from sys.columns c
join sys.tables t
on c.object_id = t.object_id
where t.name = 'TableWithTooManyVarcharColumns'
open c
fetch next from c into
@colname, @max_length
while @@FETCH_STATUS = 0
begin
set @sql = 'SELECT ''' + QUOTENAME(@colname) + ''', ' + @max_length + ' [MaxLength],' +
'MAX(LEN('+QUOTENAME(@colname)+')) as [MaxUsedLength],
AVG(LEN('+QUOTENAME(@colname)+')) as [AvgUsedLength],
STDEV(LEN('+QUOTENAME(@colname)+')) as [StdDev]
FROM TableWithTooManyVarcharColumns'
exec(@sql)
fetch next from c
into @colname, @max_length
end
close c
deallocate c
答案 1 :(得分:2)
为了完整起见,我将添加原来是我的解决方案。这是swasheck的解决方案的模式,所以他得到了他的答案,并且这个解决方案有点混乱,但它应该作为任何其他可能遇到这个问题的人的基础:
DECLARE @TableName nvarchar(100) = 'TableToAnalyze' -- Change to your table name
declare @SQLStat nvarchar(4000)
declare @ColName nvarchar(100)
declare @MaxLength integer
declare @MaxUsedLength integer
declare @AvgUsedLength float
declare @StdDev float
declare @parm1IN nvarchar(100)
declare @parm2IN integer
declare @parm3IN integer
declare @parm4IN float
declare @parm5IN float
declare @parm1O integer
declare @parm2O float
declare @parm3O float
CREATE TABLE #Details (
ColumnName nvarchar(100) NULL,
MaxLength integer null,
MaxUsedLength integer null,
AvgUsedLength float null,
StdDev float null
)
declare c cursor for
select c.name, c.max_length
from sys.columns c
join sys.tables t
on c.object_id = t.object_id
where t.name = @TableName
and c.user_type_id = 167
DECLARE @ParmDefinition1 NVARCHAR(500)
SET @ParmDefinition1 = N'@parm1IN nvarchar(100),
@parm1O int OUTPUT,
@parm2O float OUTPUT,
@parm3O float OUTPUT'
DECLARE @ParmDefinition2 NVARCHAR(500)
SET @ParmDefinition2 = N'@parm1IN nvarchar(100),
@parm2IN int,
@parm3IN int,
@parm4IN float,
@parm5IN float'
open c
fetch next from c into
@ColName, @MaxLength
while @@FETCH_STATUS = 0
begin
set @SQLStat = N'SELECT @parm1O = MAX(LEN('+ QUOTENAME(@ColName) + ')),
@parm2O = AVG(LEN('+ QUOTENAME(@ColName) + ')),
@parm3O = STDEV(LEN('+ QUOTENAME(@ColName) + '))
FROM ' + QUOTENAME(@TableName)
EXECUTE sp_executesql @SQLStat, @ParmDefinition1,
@parm1IN = @ColName,
@parm1O = @MaxUsedLength OUTPUT,
@parm2O = @AvgUsedLength OUTPUT,
@parm3O = @StdDev OUTPUT
set @SQLStat = 'INSERT INTO #Details ( ColumnName, MaxLength, MaxUsedLength, AvgUsedLength, StdDev)'
+ ' VALUES(@parm1IN, @parm2IN, @parm3IN, @parm4IN, @parm5IN)'
EXECUTE sp_executesql @SQLStat, @ParmDefinition2,
@parm1IN = @ColName,
@parm2IN = @MaxLength,
@parm3IN = @MaxUsedLength,
@parm4IN = @AvgUsedLength,
@parm5IN = @StdDev
fetch next from c
into @ColName, @MaxLength
end
close c
deallocate c
SELECT * FROM #Details
DROP TABLE #Details