SQL实现按最大长度30拆分字符串且不截断完整单词的解决方案问询
解决方案:按单词拆分字符串为指定长度的多行
我完全懂你的困扰——直接用SUBSTRING按固定长度硬切,很容易把好好的单词劈成两半,完全不符合需求。下面给你一个基于递归CTE的方案,它会自动找到每行的最后一个空格来拆分,既保证每行长度不超30字符,又不会截断完整单词。
完整实现代码
DECLARE @FullAddress VARCHAR(MAX)= '216 Apartment123 AreaArea SampleWord1 Word2 MiddleTown Upper1Location Another5 NewYork'; DECLARE @MaxLength INT = 30; WITH SplitAddress AS ( -- 初始化:处理第一个文本片段 SELECT 1 AS RowNum, -- 取前30字符内的最后一个空格位置,确保不截断单词 CASE WHEN LEN(@FullAddress) <= @MaxLength THEN @FullAddress ELSE LEFT(@FullAddress, @MaxLength - CHARINDEX(' ', REVERSE(LEFT(@FullAddress, @MaxLength)))) END AS Result, -- 计算剩余未处理的文本 CASE WHEN LEN(@FullAddress) <= @MaxLength THEN '' ELSE LTRIM(SUBSTRING(@FullAddress, @MaxLength - CHARINDEX(' ', REVERSE(LEFT(@FullAddress, @MaxLength))) + 1, LEN(@FullAddress))) END AS RemainingText UNION ALL -- 递归处理剩余文本,直到所有内容拆分完成 SELECT RowNum + 1, CASE WHEN LEN(RemainingText) <= @MaxLength THEN RemainingText ELSE LEFT(RemainingText, @MaxLength - CHARINDEX(' ', REVERSE(LEFT(RemainingText, @MaxLength)))) END, CASE WHEN LEN(RemainingText) <= @MaxLength THEN '' ELSE LTRIM(SUBSTRING(RemainingText, @MaxLength - CHARINDEX(' ', REVERSE(LEFT(RemainingText, @MaxLength))) + 1, LEN(RemainingText))) END FROM SplitAddress WHERE RemainingText <> '' ) SELECT RowNum AS [Row], Result FROM SplitAddress;
代码逻辑说明
- 递归CTE核心:通过
SplitAddress这个公用表表达式,先处理第一行,再递归处理剩下的文本,直到没有剩余内容。 - 避免单词截断的关键:用
REVERSE(LEFT(文本, 30))反转前30个字符,再用CHARINDEX找到第一个空格(也就是原文本前30字符里的最后一个空格),这样就能保证当前行只包含完整的单词。 - 清理空格:用
LTRIM去掉剩余文本开头的空格,避免拆分后的行出现前置空格。
运行结果
执行这段代码后,会完全符合你的期望输出:
+-----+------------------------------+ | Row | Result | +-----+------------------------------+ | 1 | 216 Apartment123 AreaArea | | 2 | SampleWord1 Word2 MiddleTown | | 3 | Upper1Location Another5 | | 4 | NewYork | +-----+------------------------------+
极端情况处理(可选)
如果你的字符串里存在单个单词长度超过30字符的情况(比如一个35字符的长单词),上面的代码会因为找不到空格而报错。你可以修改CASE判断,加入无空格时的处理逻辑,直接截取前30字符:
CASE WHEN LEN(RemainingText) <= @MaxLength THEN RemainingText ELSE -- 如果前30字符里没有空格,直接截取30位(避免无限递归) CASE WHEN CHARINDEX(' ', LEFT(RemainingText, @MaxLength)) = 0 THEN LEFT(RemainingText, @MaxLength) ELSE LEFT(RemainingText, @MaxLength - CHARINDEX(' ', REVERSE(LEFT(RemainingText, @MaxLength)))) END END
内容的提问来源于stack exchange,提问作者Teknas
相关产品推荐
相关产品推荐

