STRING_SPLIT函数基本用法需传入string和separator两个必填参数,分别指定待拆分字符串和单字符分隔符;SQL Server 2022起支持第三个enable_ordinal参数(设为1)以返回value和ordinal两列,确保原始顺序。

STRING_SPLIT 函数的基本用法和必要参数
SQL Server 2022 中 STRING_SPLIT 是唯一原生支持字符串拆分的系统函数,它把一个字符串按指定分隔符切开,返回带 value 列的单列表结果集。必须传入两个参数:string(待拆分字符串)和 separator(单字符分隔符),不支持多字符或正则。
常见错误是传入空字符串、NULL 或长度超过 1 的分隔符——这会导致整个查询报错:Msg 214, Level 16, State 2, Procedure STRING_SPLIT: Parameter '@separator' must be a single-character string.
- 确保分隔符是单个字符,比如
',',不能用', '(带空格)或'|'(若业务中实际是竖线需单独处理) - 输入字符串为
NULL时,STRING_SPLIT返回空结果集(不是一行NULL),注意外连接逻辑是否因此断裂 - 拆分后
value列类型始终是NVARCHAR(4000),即使源字段是VARCHAR(MAX),长文本会被截断
处理逗号分隔字符串并保留原始顺序
STRING_SPLIT 在 SQL Server 2022 中默认不保证输出顺序,尤其当配合 JOIN 或子查询使用时,行序可能错乱。如果原始字符串是 'apple,banana,cherry',你不能依赖 SELECT value FROM STRING_SPLIT(...) 的返回顺序就是从左到右。
解决办法是显式启用 ordinal 参数(SQL Server 2022+ 支持):
SELECT value, ordinal
FROM STRING_SPLIT('apple,banana,cherry', ',', 1);
第三个参数设为 1 表示开启序号输出,返回列含 ordinal(从 1 开始整数),之后可按此排序。漏掉这个参数或设为 0 就没这列。
- 必须写成
STRING_SPLIT(string, sep, 1),不能省略第三个参数或传非 1 值 -
ordinal是INT类型,可用于ORDER BY ordinal或与主表ROW_NUMBER()对齐 - 如果上游数据来自
CHARINDEX+SUBSTRING拆分的老逻辑,迁移到STRING_SPLIT(..., ..., 1)后要同步检查排序逻辑是否失效
与表连接时避免隐式转换和空值干扰
实际场景常是:某订单表 Orders 有个 product_ids 字段存 '101,102,105',想关联查出具体商品名。直接 JOIN 容易因类型/空值翻车。
典型陷阱包括:product_ids 字段为空字符串、仅空格、或含不可见字符(如 CHAR(13)+CHAR(10)),导致 STRING_SPLIT 返回意外空行;或者 value 是字符串而目标表主键是 INT,隐式转换失败报错 Conversion failed when converting the varchar value '101 ' to data type int.(注意末尾空格)。
- 拆分前先
TRIM和NULLIF:用NULLIF(TRIM(product_ids), '')过滤掉纯空格或空串 - 拆分后对
value显式TRIM再转类型:TRY_CAST(TRIM(s.value) AS INT),比CAST更安全 - 避免在
ON条件里直接写o.id = CAST(s.value AS INT),应先在子查询里清理好value
性能和替代方案的边界在哪里
STRING_SPLIT 是标量函数,但执行计划里常表现为“内联函数”,多数情况下比自定义拆分函数快。不过它不适合高频、大数据量(如单次拆分 >10 万元素)或需要嵌套拆分(如先按分号再按逗号)的场景。
如果发现执行计划出现大量 Table Spool 或 Compute Scalar 节点,且 STRING_SPLIT 调用在循环中(如游标或 TVF 内多次调用),性能会明显下滑。这时该考虑预处理:把原始字符串提前拆好存入关联表,或改用 JSON 解析(OPENJSON)——前提是字符串能格式化为合法 JSON 数组,例如 '["101","102","105"]'。
- 单次拆分元素数建议控制在 1000 以内,超了要考虑应用层拆分
- 不要在
WHERE子句里对大字段反复调用STRING_SPLIT,比如WHERE EXISTS (SELECT 1 FROM STRING_SPLIT(large_col, ',') s WHERE s.value = 'x') - SQL Server 2022 支持
STRING_AGG反向聚合,但二者不互逆:用STRING_SPLIT拆完再STRING_AGG拼回去,空值和重复分隔符行为可能不一致
最易被忽略的是:即使启用了 ordinal,它也不代表原始字符串中的逻辑位置(比如跳过空元素后的偏移),而是严格按分割动作生成的序号。如果你的业务规则要求“跳过空项后重新编号”,还得自己加 ROW_NUMBER() OVER (ORDER BY ordinal) 过滤后再重排。

















