SQL Server 2012 将字符串按分隔符分成三列

SQL Server 2012 divide string into three columns by deliminter

用多个定界符分隔下面的字符串时遇到问题

示例数据

            column1
row1   'ABC>DEF>GHI'
row2   'ABC>DEF>GHI'
row3   'ABC>DEF'
row4   'ABC>DEF'
row5   'ABC>DEF>GHI'

目标

      col1  col2  col3
row1  'ABC' 'DEF' 'GHI'
row2  'ABC' 'DEF' 'GHI'
row3  'ABC' 'DEF'
row4  'ABC' 'DEF'
row5  'ABC' 'DEF' 'GHI'

我想将这一行分成 3 列,每列前后 >

我已经管理了这 2 个在第一个定界符之前和最后一个定界符之后捕获的 case 语句,但我一直在两个定界符之间捕获。

CASE 
   WHEN Indicator LIKE '%>%' 
     THEN LEFT (column1, Charindex('>' , column1) - 1) 
     ELSE col1 
END as col1

CASE 
   WHEN Indicator LIKE '%>%' 
      THEN RIGHT (column1, Charindex('>' , Reverse(column1)) - 1) 
END as col3

如有任何帮助,我们将不胜感激

谢谢

使用 Parsename 函数技巧来做到这一点。

SELECT Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 1)) col1,
       Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 2)) col2,
       Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 3)) col3
FROM   tablename

演示

create table #test(   column1 varchar(500))
insert #test values
('ABC > DEF > GHI'),
('ABC > DEF > GHI'),
('ABC > DEF      '),
('ABC > DEF      '),
('ABC > DEF > GHI')

SELECT Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 1)) col1,
       Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 2)) col2,
       Reverse(Parsename(Reverse(Replace(column1, ' > ', '.')), 3)) col3
FROM   #test 

结果:

col1    col2    col3
----    ----    ----
ABC     DEF     GHI
ABC     DEF     GHI
ABC     DEF     NULL
ABC     DEF     NULL
ABC     DEF     GHI

您不应在单个字段中存储定界字符串,因为这取决于您。假设您别无选择,只能解析定界字符串,这是我经常使用的解析函数:

/********************************************************************************************
        Create Parse Function
********************************************************************************************/
CREATE FUNCTION dbo.FN_PARSE(@chunk VARCHAR(4000), @delimiter CHAR(1), @index INT )
RETURNS VARCHAR(1000)
AS
BEGIN
    DECLARE
        @curIndex INT = 0,
        @pos INT = 1,
        @prevPos INT = 0,
        @result VARCHAR(1000)
    WHILE @pos > 0
    BEGIN
        SET @pos =  CHARINDEX(@delimiter, @chunk, @prevPos);
        IF(@pos > 0)
        BEGIN -- Characters between position and previous position
            SET @result = SUBSTRING(@chunk, @prevPos, @pos-@prevPos)
        END
        ELSE
        BEGIN -- Last Delim
            SET @result = SUBSTRING(@chunk, @prevPos, LEN(@chunk))
        END
        IF(@index = @curIndex)
        BEGIN
            RETURN @result
        END
        SET @prevPos = @pos + 1
        SET @curIndex = @curIndex + 1;
    END
    RETURN '' -- Else Empty
END

用法很简单,用三个参数调用函数,字段、分隔符和索引return。

SELECT dbo.FN_PARSE(column1,'>', 0) AS Col1
      ,dbo.FN_PARSE(column1,'>', 1) AS Col2
      ,dbo.FN_PARSE(column1,'>', 2) AS Col3
FROM YourTable

请注意索引值从 0 开始。与 PARSENAME() 不同,这将处理超过 4 个部分,但这也可能效率较低。