如何在MSSQL存储过程中正确反转CSV拆分后的行顺序?
问题分析
你的存储过程没能按预期反转行顺序,核心问题有两个:
STRING_SPLIT函数返回的结果不保证与原CSV字符串中的行顺序一致,默认也不会提供行的原始序号;- 你后续使用的
ORDER BY row DESC是按字符串字典序排序,不是按原CSV的行顺序反转,所以得到的结果和预期不符。
解决方案
要实现原CSV行顺序的反转,必须先保留拆分后每行在原字符串中的顺序,再按该顺序的倒序排列。
方案1:SQL Server 2022 及以上版本(推荐)
SQL Server 2022 给 STRING_SPLIT 新增了 enable_ordinal 参数,可直接返回每行的原始序号:
ALTER PROCEDURE [dbo].[MY_STOREDPROC] @csv_string NVARCHAR(MAX), @separator NCHAR(1)= '#' AS BEGIN -- 声明带序号的表变量 DECLARE @csv_table TABLE (row_order INT, row NVARCHAR(MAX)) -- 拆分CSV并保留原顺序的序号 INSERT INTO @csv_table (row_order, row) SELECT ordinal, value FROM STRING_SPLIT(@csv_string, @separator, 1) -- 第三个参数1启用ordinal字段 WHERE LEN(value) > 0 -- 输出原顺序的行 SELECT row FROM @csv_table ORDER BY row_order -- 输出反转后的行(按原序号倒序排列) SELECT row FROM @csv_table ORDER BY row_order DESC END
方案2:SQL Server 2022 以下版本
如果使用旧版本SQL Server,可通过递归CTE实现带顺序的CSV拆分:
ALTER PROCEDURE [dbo].[MY_STOREDPROC] @csv_string NVARCHAR(MAX), @separator NCHAR(1)= '#' AS BEGIN -- 声明带序号的表变量 DECLARE @csv_table TABLE (row_order INT, row NVARCHAR(MAX)) -- 递归CTE拆分CSV并保留行顺序 ;WITH SplitCTE AS ( SELECT 1 AS row_order, CHARINDEX(@separator, @csv_string) AS sep_pos, LEFT(@csv_string, CHARINDEX(@separator, @csv_string) - 1) AS row WHERE @csv_string IS NOT NULL AND CHARINDEX(@separator, @csv_string) > 0 UNION ALL SELECT row_order + 1, CHARINDEX(@separator, @csv_string, sep_pos + 1), SUBSTRING(@csv_string, sep_pos + 1, CHARINDEX(@separator, @csv_string, sep_pos + 1) - sep_pos - 1) FROM SplitCTE WHERE sep_pos > 0 UNION ALL SELECT ISNULL((SELECT MAX(row_order) + 1 FROM SplitCTE), 1) AS row_order, 0, @csv_string AS row WHERE CHARINDEX(@separator, @csv_string) = 0 ) INSERT INTO @csv_table (row_order, row) SELECT row_order, row FROM SplitCTE WHERE LEN(row) > 0 -- 输出原顺序的行 SELECT row FROM @csv_table ORDER BY row_order -- 输出反转后的行 SELECT row FROM @csv_table ORDER BY row_order DESC END
效果验证
修改后执行存储过程,反转结果将与你期望的完全一致:
row ----------------------- Miya,Marksman,Gold,Female,25 Zed,Smith,Garcia,Female,17 Anne,Poe,Rodriguez,Male,30 Mark,Fernandez,Rodriguez,Male,25
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

