You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用CHARINDEX拆分字符串至多列遇问题:结果行重复且列值错误

解决SQL自定义拆分函数的多行与列值错误问题

我仔细看了你的函数代码和遇到的问题,这两个问题其实是因为函数里的逻辑没处理好拆分段的分配和插入方式导致的,咱们一步步来修正:

原函数的核心问题

  • 多行记录问题:你在函数里多次执行INSERT INTO @returnList,每次只插一列,自然会生成多条记录,而不是一条记录包含所有列。
  • 列值重复错误:循环里每次都把@cassette_1到@cassette_4全赋值成当前拆分的第一段,完全没区分不同的拆分段,最后所有变量都会被覆盖成最后一次循环的内容。
  • 另外,原逻辑没处理分隔符连续出现的情况(比如末尾的aaaad),会导致空值混入。

修正后的自定义函数

CREATE FUNCTION dbo.splitstring ( @stringToSplit VARCHAR(MAX) )
RETURNS @returnList TABLE (
    [first_segment] [nvarchar] (500),
    [remaining_note] [nvarchar] (500),
    [cassette_1] [nvarchar] (500),
    [cassette_2] [nvarchar] (500),
    [cassette_3] [nvarchar] (500),
    [cassette_4] [nvarchar] (500),
    [total] [nvarchar] (500)
)
AS
BEGIN
    DECLARE @first_segment NVARCHAR(255)
    DECLARE @remaining_note NVARCHAR(255)
    DECLARE @cassette_1 NVARCHAR(255)
    DECLARE @cassette_2 NVARCHAR(255)
    DECLARE @cassette_3 NVARCHAR(255)
    DECLARE @cassette_4 NVARCHAR(255)
    DECLARE @total NVARCHAR(255)
    DECLARE @pos INT
    DECLARE @segment_count INT = 1 -- 跟踪当前是第几个拆分段
    DECLARE @current_segment NVARCHAR(255)

    -- 先处理掉末尾的无效字符,避免空段干扰
    SET @stringToSplit = RTRIM(LTRIM(REPLACE(@stringToSplit, 'aaaad', '')))

    WHILE CHARINDEX('a ', @stringToSplit) > 0
    BEGIN
        SELECT @pos = CHARINDEX('a ', @stringToSplit)
        SELECT @current_segment = LTRIM(SUBSTRING(@stringToSplit, 1, @pos - 1)) -- 去掉段前的空格

        -- 根据当前段的序号赋值给对应的变量
        IF @segment_count = 1
            SET @first_segment = @current_segment
        ELSE IF @segment_count = 2
            SET @remaining_note = @current_segment
        ELSE IF @segment_count = 3
            SET @cassette_1 = @current_segment
        ELSE IF @segment_count = 4
            SET @cassette_2 = @current_segment
        ELSE IF @segment_count = 5
            SET @cassette_3 = @current_segment
        ELSE IF @segment_count = 6
            SET @cassette_4 = @current_segment
        ELSE IF @segment_count = 7
            SET @total = @current_segment

        -- 截取剩余字符串继续处理
        SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos + 2, LEN(@stringToSplit) - @pos - 1)
        SET @segment_count = @segment_count + 1
    END

    -- 处理最后一段(如果循环结束后还有剩余)
    IF LTRIM(@stringToSplit) <> ''
        SET @total = LTRIM(@stringToSplit)

    -- 只插入一条记录,包含所有列
    INSERT INTO @returnList (first_segment, remaining_note, cassette_1, cassette_2, cassette_3, cassette_4, total)
    VALUES (@first_segment, @remaining_note, @cassette_1, @cassette_2, @cassette_3, @cassette_4, @total)

    RETURN
END

关键点说明

  1. 添加段计数器:用@segment_count跟踪当前拆分到第几个段,对应赋值给不同的变量,不会再全部覆盖成同一个值。
  2. 单次插入记录:所有变量赋值完成后,只执行一次INSERT,确保生成单条记录。
  3. 清理无效字符:提前处理末尾的aaaad,避免空段干扰拆分逻辑。
  4. 去除段前空格:用LTRIM处理每个拆分段,避免开头的多余空格。

调用测试

执行你的调用代码后,就能得到单条记录,且每个列对应正确的内容:

SELECT * FROM dbo.splitstring('005031812180200000100aRemaining Inside Terminala Cassette 1(BIN1)/c:HTG 21,000a Cassette 2(BIN2)/c:HTG 23,000a Cassette 3(BIN3)/d:HTG 47,000a Cassette 4(BIN4)/d:HTG 48,000a Total : HTG 139,000aaaad')

结果示例:

first_segmentremaining_notecassette_1cassette_2cassette_3cassette_4total
005031812180200000100Remaining Inside TerminalCassette 1(BIN1)/c:HTG 21,000Cassette 2(BIN2)/c:HTG 23,000Cassette 3(BIN3)/d:HTG 47,000Cassette 4(BIN4)/d:HTG 48,000Total : HTG 139,000

内容的提问来源于stack exchange,提问作者Manuel Yumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:02:28