string_split在sql server 2022中默认不保序,需指定第三个参数1启用ordinal列以确保顺序;空值需trim+where过滤;性能优化依赖临时表索引或表值参数。

STRING_SPLIT 在 SQL Server 2022 中默认仍不保序
直接写 SELECT value FROM STRING_SPLIT('a,b,c', ','),结果顺序不保证——哪怕只跑一次,也可能返回 b、a、c。这不是 bug,是设计行为。SQL Server 不承诺表值函数的物理行序,除非你显式启用位置信息。
必须加第三个参数 1 才能拿到原始顺序
SQL Server 2022+ 的关键增强是 enable_ordinal 参数,值为 1 时返回两列:value 和 ordinal(从 1 开始的原始位置编号)。
正确写法:
SELECT value, ordinal
FROM STRING_SPLIT('苹果,香蕉,橙子', ',', 1);
返回:
value | ordinal
苹果 | 1
香蕉 | 2
橙子 | 3
注意:ordinal 是 bigint 类型,且仅当第三个参数为 1(或非零整数/true)时存在;传 0、NULL 或省略,就退化回无序单列。
连续分隔符和首尾空格不会自动清理
STRING_SPLIT 只做机械切分,不做语义清洗。输入 ' a ,,b ' 会返回四行:' a '、''、''、'b '。
- 过滤空项:
WHERE TRIM(value) != '' - 统一去空格:
TRIM(value) AS clean_value - 转数字前务必检查:
TRY_CAST(TRIM(value) AS INT),避免CAST因空串直接报错
CROSS APPLY 中使用要防嵌套性能陷阱
在关联拆分场景(如一行变多行),必须用 CROSS APPLY,不能塞进 WHERE IN 子查询里。
安全写法:
SELECT t.id, s.value, s.ordinal FROM orders t CROSS APPLY STRING_SPLIT(t.tag_list, ',', 1) AS s WHERE TRIM(s.value) != '';
容易踩的坑:
- 漏掉
AS s别名 → 报错Incorrect syntax near '(' - 没加
WHERE TRIM(s.value) != ''→ 空串参与JOIN或IN可能意外匹配空字段 - 在大表上反复调用,又没建临时表索引 → 执行计划常退化为嵌套循环 + 全表扫描
真正难处理的不是语法,而是把“顺序”“空值”“性能”三者同时稳住——ordinal 解了顺序,TRIM + WHERE 解了空值,而性能得靠提前落临时表+索引,或改用表值参数(TVP)。










