SQL Server存储过程中如何获取变量指定列的实际数据
问题根因
T-SQL 不支持在普通查询语句中直接用变量代替标识符(列名、表名等)。你写的select distinct @column_name from AogerCnlyOi.dbo.CnlyOiDealAnalysis会被解析器判定为「查询一个固定字符串常量」,因此返回的每一行结果都是@column_name变量存储的字符串值,不会读取对应列的实际存储数据。
要实现动态列名查询,必须通过动态SQL拼接出语法完整的合法查询语句,再调用系统存储过程执行。
修正后的存储过程代码
USE AogerCnlyOi GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER OFF GO CREATE PROCEDURE [dbo].[QC_Actian_SSIS] AS BEGIN DECLARE @column_name VARCHAR(MAX) DECLARE @data_type VARCHAR(MAX) DECLARE @exec_sql NVARCHAR(MAX) -- 存储拼接完成的动态查询语句 DECLARE cur_tracking CURSOR FOR SELECT column_name,data_type FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='CnlyOiDealAnalysis' ORDER BY ordinal_position OPEN cur_tracking; FETCH NEXT FROM cur_tracking INTO @column_name,@data_type; WHILE @@Fetch_status=0 BEGIN -- 拼接查询语句,QUOTENAME会自动给列名加方括号,兼容特殊字符列名、防范SQL注入 SET @exec_sql = N'SELECT DISTINCT ' + QUOTENAME(@column_name) + N' AS column_value FROM AogerCnlyOi.dbo.CnlyOiDealAnalysis' -- 执行动态SQL EXEC sp_executesql @exec_sql FETCH NEXT FROM cur_tracking INTO @column_name,@data_type; END; CLOSE cur_tracking; DEALLOCATE cur_tracking; END GO
关键说明
- 禁止直接拼接
@column_name到SQL字符串中,必须使用QUOTENAME()函数包裹列名,否则遇到带空格、关键字、特殊符号的列名会直接报错,同时存在SQL注入风险。 - 存储动态SQL语句的变量必须声明为
NVARCHAR类型,这是系统存储过程sp_executesql的入参要求。 - 上述代码执行后,会按列的顺序依次返回每列的去重结果集。如果需要把所有列的去重结果汇总到同一张结果表,可以在动态SQL中增加列名标识字段,将结果插入统一的临时表或物理表中。
内容的提问来源于stack exchange,提问作者Dikshit Karki
相关产品推荐
相关产品推荐

