从我的角度来看,一个查询是不可能的。但是,如果您之前转换为 NVARCHAR(MAX),您可以收集基本数据并运行您的 MAX (LEN()),那么日期大小会看起来更真实 - 我已经在循环中使用 try-catch万一演员失败。下面是一个示例(我使用了架构名称以防您想区分表)
DECLARE @Table VARCHAR(255) = 'Customer'
DECLARE @Schema VARCHAR(255) = 'dbo'
DECLARE @i INT
DECLARE @j INT
DECLARE @sql NVARCHAR(MAX)
DECLARE @buffer TABLE (buffer_value VARCHAR(255))
DECLARE @actual_max_size INT
DECLARE @sch_table_name VARCHAR(255)
DECLARE @column_name VARCHAR(255)
DECLARE @TbList TABLE (
id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
sch_name VARCHAR(255),
table_name VARCHAR(255),
column_name VARCHAR(255),
datatype_name VARCHAR(255),
type_length INT,
actual_max_size INT )
INSERT INTO @TbList
( sch_name ,
table_name ,
column_name ,
datatype_name ,
type_length )
SELECT
s.name AS sch_name,
t.name AS table_name,
c.name AS column_name,
y.name AS datatype_name,
c.max_length AS type_length
FROM sys.tables t
JOIN sys.schemas s
ON t.schema_id = s.schema_id
JOIN sys.columns c
ON t.object_id = c.object_id
JOIN sys.types y
ON c.user_type_id = y.user_type_id
WHERE t.name = @Table
AND s.name = @Schema
SET @i = (SELECT MIN(id) FROM @TbList )
SET @j = (SELECT MAX(id) FROM @TbList )
WHILE @i <= @j
BEGIN
DELETE FROM @buffer
SET @sch_table_name = (SELECT sch_name+'.'+table_name FROM @TbList WHERE id = @i)
SET @column_name = (SELECT column_name FROM @TbList WHERE id = @i)
SET @sql = ('SELECT MAX(LEN(CAST ('+@column_name+' AS NVARCHAR(MAX)))) FROM '+@sch_table_name+'')
BEGIN TRY
INSERT INTO @buffer (buffer_value) EXEC (@sql)
SET @actual_max_size = (SELECT TOP 1 buffer_value FROM @buffer)
END TRY
BEGIN CATCH
SET @actual_max_size = -1
PRINT ERROR_MESSAGE()
END CATCH
IF @actual_max_size IS NULL
BEGIN
SET @actual_max_size = 0
END
UPDATE @TbList SET actual_max_size = @actual_max_size WHERE id = @i
SET @i = @i+1
END
SELECT * FROM @TbList
几个 cmets:我使用循环来一一获取每一列的 MAX LEN。这不是最优雅的方法,但效果很好。如果桌子很大,可能需要一些时间。
注意:要在循环中运行查询,我们必须在动态 SQL 中进行。那么问题就是将动态 SQL 的输出带回主查询并更新内存表。 sp_executesql 可以做到这一点,但我发现上面的解决方案更快:
我的解决方案是基于我们可以将动态 SQL 查询的输出插入到表中的原理。然后我创建一个缓冲区表来存储查询结果,并使用该缓冲区表中的 select top 1 更新变量(在循环开始时清空)。不是很优雅,但工作正常。