SQL Server 2019动态PIVOT并行执行无冲突最优方案问询
解决SQL Server动态PIVOT多用户并行+非共享临时表问题
首先,咱们直接说核心:**局部临时表(以#开头)**就是SQL Server里实现会话隔离、多用户并行不干扰的最优解,完全不需要锁或者提前清空表——因为每个用户的会话都会创建属于自己的独立临时表,互相根本看不见。
你遇到的Msg 2018错误,大概率是这几个原因之一:要么是之前误用了全局临时表(##开头)导致命名冲突,要么是动态生成列时没处理好排序规则,或者是跨上下文访问临时表的问题。下面给你SQL Server 2019里最简洁的解决方案,完美适配你的需求:
修改后的存储过程代码
CREATE OR ALTER PROCEDURE dbo.DynamicPivotForUsers AS BEGIN SET NOCOUNT ON; -- 1. 用局部临时表存源数据,避免永久表的共享冲突 DECLARE @COMMA_SEPARATED_KEYS varchar(MAX); DROP TABLE IF EXISTS #SourceKV; CREATE TABLE #SourceKV (id_person int, mykey varchar(30), myvalue int); INSERT INTO #SourceKV VALUES (1, 'age', 16), (1, 'weight', 63), (1, 'height', 175), (2, 'age', 26), (2, 'weight', 83), (2, 'height', 185); -- 2. 动态获取所有唯一的mykey,用QUOTENAME包裹列名避免语法错误 WITH UniqueKeys(mykey) AS ( SELECT DISTINCT mykey FROM #SourceKV ) SELECT @COMMA_SEPARATED_KEYS = STRING_AGG(QUOTENAME(mykey), ',') FROM UniqueKeys; -- 3. 构建动态PIVOT语句,使用局部临时表#Pivoted DECLARE @DynamicSQL nvarchar(MAX); SET @DynamicSQL = N' DROP TABLE IF EXISTS #Pivoted; SELECT * INTO #Pivoted FROM ( SELECT id_person, mykey, myvalue FROM #SourceKV ) AS SourceData PIVOT( MAX(SourceData.myvalue) FOR mykey IN (' + @COMMA_SEPARATED_KEYS + ') ) AS PivotResult; -- 直接返回透视后的结果,或者后续在存储过程里继续使用#Pivoted SELECT * FROM #Pivoted; '; -- 执行动态SQL EXEC sp_executesql @DynamicSQL; -- 如果需要在存储过程后续逻辑中使用透视表,直接访问即可 -- SELECT * FROM #Pivoted; END GO
为什么这个方案能解决你的问题?
会话级隔离,多用户并行无干扰:
局部临时表(#开头)只属于当前执行会话,每个用户调用存储过程时,都会创建自己的#SourceKV和#Pivoted,其他用户完全看不到这些表,自然不会有冲突。新增字段无需修改代码:
当你新增foot_width这类字段时,STRING_AGG会自动从#SourceKV里抓取新的mykey值,生成对应的透视列,完全不用改存储过程代码。避免语法错误和排序规则问题:
用QUOTENAME包裹列名,就算mykey里有空格、特殊字符也不会报错;如果确实遇到排序规则冲突(Msg 2018的常见原因),可以在获取唯一键时指定统一排序规则:WITH UniqueKeys(mykey) AS ( SELECT DISTINCT mykey COLLATE SQL_Latin1_General_CP1_CI_AS FROM #SourceKV )
关于你提到的“提前清空表或用锁”
完全没必要!局部临时表本身就是会话隔离的,每个用户的表都是独立的,不存在“多个用户操作同一张表”的场景,所以不需要清空,也不需要加锁——加锁反而会降低并行性能。
内容的提问来源于stack exchange,提问作者Ludovic Aubert
相关产品推荐
相关产品推荐

