使用Fetch Cursor时如何删除最后一个UNION关键字
解决动态UNION查询末尾多余UNION关键字的问题
嘿,这个动态拼接UNION的坑我之前也踩过好几次,太懂这种末尾多一个UNION的烦躁了~给你几个实用的解决思路,你可以根据自己的SQL Server版本和场景来选:
方法1:用STRING_AGG拼接(SQL Server 2017+ 推荐)
这是最简洁的方式,先把所有要执行的SELECT语句收集到临时表/表变量里,再用STRING_AGG自动用UNION连接,完全不用担心末尾多关键字的问题:
DECLARE @selects TABLE (sql_stmt NVARCHAR(MAX)) DECLARE @temp NVARCHAR(MAX) -- 假设你的游标已经定义并打开 WHILE @@FETCH_STATUS = 0 BEGIN -- 把每个SELECT语句存入临时表 INSERT INTO @selects (sql_stmt) VALUES ('select ' + @temp + ' from table_A') FETCH NEXT FROM cur INTO @temp END -- 用STRING_AGG自动拼接UNION,换行符让语句更易读 SET @query = STRING_AGG(sql_stmt, CHAR(13) + 'UNION' + CHAR(13)) FROM @selects
方法2:先拼接再移除末尾的UNION
如果你的SQL Server版本比较老,不能用STRING_AGG,可以先按你原来的逻辑拼接所有内容,最后去掉末尾的UNION和换行符:
DECLARE @query NVARCHAR(MAX) = '' DECLARE @temp NVARCHAR(MAX) -- 游标打开后执行循环 WHILE @@FETCH_STATUS = 0 BEGIN SET @query = @query + 'select ' + @temp + ' from table_A' + CHAR(13) + 'UNION' + CHAR(13) FETCH NEXT FROM cur INTO @temp END -- 检查拼接后的内容不为空,再移除末尾的UNION及前后换行 IF LEN(@query) > 0 BEGIN -- 计算要移除的长度:UNION(5) + 前后两个CHAR(13)(各1),总共7个字符 SET @query = LEFT(@query, LEN(@query) - 7) -- 要是不确定换行符数量,也可以用STUFF更灵活: -- SET @query = STUFF(@query, LEN(@query) - CHARINDEX('UNION', REVERSE(@query)) + 1, LEN('UNION'), '') END
方法3:判断首条语句,仅后续语句前加UNION
这种方法逻辑更稳妥,从根源上避免末尾出现多余的UNION:先标记是否是第一条查询,第一条直接赋值SELECT,之后的每条都先加UNION再拼接SELECT:
DECLARE @query NVARCHAR(MAX) = '' DECLARE @temp NVARCHAR(MAX) DECLARE @is_first BIT = 1 -- 游标打开后执行循环 WHILE @@FETCH_STATUS = 0 BEGIN IF @is_first = 1 BEGIN -- 第一条语句直接拼接,不加UNION SET @query = 'select ' + @temp + ' from table_A' SET @is_first = 0 END ELSE BEGIN -- 非第一条语句,先加UNION再拼接SELECT SET @query = @query + CHAR(13) + 'UNION' + CHAR(13) + 'select ' + @temp + ' from table_A' END FETCH NEXT FROM cur INTO @temp END
如果是SQL Server 2017及以上,优先选方法1,代码最简洁;老版本的话方法3逻辑更清晰,不容易出错~
内容的提问来源于stack exchange,提问作者Randy Adhitama
相关产品推荐
相关产品推荐

