如何批量获取表中各列的长度极值、值极值及空值统计?
嘿,我来帮你解决这个批量分析大表列属性的问题!针对你有107列的MY_TABLE,要批量获取每列的长度极值、空值+空字符串数量、值的极值,我给你两个实用方案,既不用手动修改变量,也能避开直接对50万行大表做Pivot的性能顾虑:
方案一:游标循环逐个分析(直观易维护)
这个方案用游标遍历所有列,逐个执行动态SQL并把结果存入统一的临时表,最后一次性查看所有列的分析结果,适合新手理解和调试:
-- 1. 创建存储最终分析结果的临时表 CREATE TABLE #COLUMN_ANALYSIS ( COLUMN_NAME VARCHAR(128), CHR_MIN INT, -- 列值的最小长度 CHR_MAX INT, -- 列值的最大长度 EMPTY_COUNT INT, -- 空值+空字符串(含全空格)的数量 VALUE_MIN SQL_VARIANT,-- 列值的最小值(兼容多数据类型) VALUE_MAX SQL_VARIANT -- 列值的最大值(兼容多数据类型) ) -- 2. 获取MY_TABLE的所有列信息,按原始顺序存入临时表 SELECT TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION INTO #TEMP_COLS FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MY_TABLE' -- 注意表名要加引号 ORDER BY ORDINAL_POSITION -- 3. 声明游标遍历每一列 DECLARE @col VARCHAR(128) DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME FROM #TEMP_COLS OPEN col_cursor FETCH NEXT FROM col_cursor INTO @col WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @RUN_QUERY NVARCHAR(MAX) -- 生成当前列的分析SQL,用QUOTENAME处理特殊列名,sp_executesql更安全 SET @RUN_QUERY = N' INSERT INTO #COLUMN_ANALYSIS (COLUMN_NAME, CHR_MIN, CHR_MAX, EMPTY_COUNT, VALUE_MIN, VALUE_MAX) SELECT ''' + @col + ''' AS COLUMN_NAME, MIN(LEN(' + QUOTENAME(@col) + ')) AS CHR_MIN, MAX(LEN(' + QUOTENAME(@col) + ')) AS CHR_MAX, COUNT(CASE WHEN ' + QUOTENAME(@col) + ' IS NULL OR LTRIM(RTRIM(' + QUOTENAME(@col) + ')) = '''' THEN 1 END) AS EMPTY_COUNT, MIN(' + QUOTENAME(@col) + ') AS VALUE_MIN, MAX(' + QUOTENAME(@col) + ') AS VALUE_MAX FROM MY_TABLE' EXEC sp_executesql @RUN_QUERY FETCH NEXT FROM col_cursor INTO @col END -- 清理游标 CLOSE col_cursor DEALLOCATE col_cursor -- 查看所有列的分析结果 SELECT * FROM #COLUMN_ANALYSIS ORDER BY COLUMN_NAME -- 清理临时表 DROP TABLE #TEMP_COLS DROP TABLE #COLUMN_ANALYSIS
方案二:动态生成UNION ALL查询(一次性执行,效率更高)
如果想减少多次执行SQL的开销,可以把所有列的分析语句拼接成一个UNION ALL的大SQL,一次性执行完成,适合对性能要求更高的场景:
适用于SQL Server 2017+(支持STRING_AGG)
DECLARE @DynamicSQL NVARCHAR(MAX) -- 自动拼接所有列的分析语句为UNION ALL SELECT @DynamicSQL = STRING_AGG( N' SELECT ''' + COLUMN_NAME + ''' AS COLUMN_NAME, MIN(LEN(' + QUOTENAME(COLUMN_NAME) + ')) AS CHR_MIN, MAX(LEN(' + QUOTENAME(COLUMN_NAME) + ')) AS CHR_MAX, COUNT(CASE WHEN ' + QUOTENAME(COLUMN_NAME) + ' IS NULL OR LTRIM(RTRIM(' + QUOTENAME(COLUMN_NAME) + ')) = '''' THEN 1 END) AS EMPTY_COUNT, MIN(' + QUOTENAME(COLUMN_NAME) + ') AS VALUE_MIN, MAX(' + QUOTENAME(COLUMN_NAME) + ') AS VALUE_MAX FROM MY_TABLE', N' UNION ALL ' ) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MY_TABLE' ORDER BY ORDINAL_POSITION -- 执行动态SQL并直接返回结果 EXEC sp_executesql @DynamicSQL
适用于SQL Server 2016及以下版本(用FOR XML PATH拼接)
DECLARE @DynamicSQL NVARCHAR(MAX) SET @DynamicSQL = '' -- 拼接每一列的分析语句 SELECT @DynamicSQL = @DynamicSQL + N' SELECT ''' + COLUMN_NAME + ''' AS COLUMN_NAME, MIN(LEN(' + QUOTENAME(COLUMN_NAME) + ')) AS CHR_MIN, MAX(LEN(' + QUOTENAME(COLUMN_NAME) + ')) AS CHR_MAX, COUNT(CASE WHEN ' + QUOTENAME(COLUMN_NAME) + ' IS NULL OR LTRIM(RTRIM(' + QUOTENAME(COLUMN_NAME) + ')) = '''' THEN 1 END) AS EMPTY_COUNT, MIN(' + QUOTENAME(COLUMN_NAME) + ') AS VALUE_MIN, MAX(' + QUOTENAME(COLUMN_NAME) + ') AS VALUE_MAX FROM MY_TABLE' + N' UNION ALL ' FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'MY_TABLE' ORDER BY ORDINAL_POSITION -- 去掉末尾多余的UNION ALL SET @DynamicSQL = LEFT(@DynamicSQL, LEN(@DynamicSQL) - 10) -- 执行动态SQL EXEC sp_executesql @DynamicSQL
额外注意事项
- 对于数值类型的列,
LEN()会把数值转为字符串后计算长度(比如数值123的长度是3),如果不需要统计数值列的长度,可以在生成SQL时判断DATA_TYPE,只对字符类型列计算长度。 - 空值统计里的
LTRIM(RTRIM())是为了把全空格的字符串也算作“空”,如果不需要这个逻辑,直接改成col IS NULL OR col = ''即可。
内容的提问来源于stack exchange,提问作者Jan Camara
相关产品推荐
相关产品推荐

