【问题标题】:Splitting an SQL string into multiple strings将一个 SQL 字符串拆分为多个字符串
【发布时间】:2014-05-07 15:17:26
【问题描述】:

我正在尝试将包含多个电子邮件地址数据的单个字符串拆分为三个变量。字符串用 ; 标记电子邮件地址的开始/结束。字符。

一个示例字符串是:

'joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com'

我目前拥有的代码如下:

    DECLARE @Email VARCHAR(100),
        @Email2 VARCHAR(100),
        @Email3 VARCHAR(100)

SET @Email = 'joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com'

SET @Email2 = SUBSTRING(@Email, CHARINDEX(';', @Email)+1, LEN(@Email))
SET @Email3 = SUBSTRING(@Email, CHARINDEX(';', @Email)+1, LEN(@Email))
SET @Email = SUBSTRING(@Email, 1, CHARINDEX(';', @Email)-1)

不幸的是,这似乎不起作用。有人可以指出我哪里出错了,我应该怎么做才能解决我的问题?

提前致谢。

【问题讨论】:

标签: sql sql-server string substring


【解决方案1】:

假设总是有 3 个电子邮件地址 - 以下似乎可行;

DECLARE @Email VARCHAR(100),
        @Email2 VARCHAR(100),
        @Email3 VARCHAR(100)

SET @Email = 'joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com'

SELECT   @Email     = LEFT(@Email, CHARINDEX(';', @Email) - 1)
        ,@Email2    = SUBSTRING (   
                                    @Email, 
                                    CHARINDEX(';', @Email) + 1, 
                                    CHARINDEX(';', @Email, CHARINDEX(';', @Email) + 1) - LEN(LEFT(@Email, CHARINDEX(';', @Email) )) - 1
                                )
        ,@Email3    = RIGHT(@Email, CHARINDEX(';', @Email)-1)

【讨论】:

  • +1,他们的关键点是您正在使用可选的第三个参数,CHARINDEX 在给定点之后查找字符串中字符的位置以找到第二个分号(它是总是很高兴为您的答案添加一些解释,而不仅仅是提供代码)
【解决方案2】:

这个解决方案:

create function dbo.SplitString 
(
    @str nvarchar(max), 
    @separator char(1)
)
returns table
AS
return (
with tokens(p, a, b) AS (
    select 
        cast(1 as bigint), 
        cast(1 as bigint), 
        charindex(@separator, @str)
    union all
    select
        p + 1, 
        b + 1, 
        charindex(@separator, @str, b + 1)
    from tokens
    where b > 0
)
select
    p-1 ItemIndex,
    substring(
        @str, 
        a, 
        case when b > 0 then b-a ELSE LEN(@str) end) 
    AS Item
from tokens
);

GO

取自How do I split a string so I can access item x

【讨论】:

    【解决方案3】:

    在 SQL Server 2016 中,您可以使用 built-in STRING_SPLIT function

    SELECT value FROM STRING_SPLIT(@var, ';')
    

    【讨论】:

      【解决方案4】:

      尝试使用 XML 节点来拆分和解析您的字符串。下面的代码示例:

      declare @Email as varchar(100), @del as varchar(10), @xml as xml;
      set @Email='joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com';
      set @del =';';
      set @xml = '<root><c>' + replace(@Email,@del,'</c><c>') + '</c></root>';
      select email.value('.','varchar(100)') as Email
      from @xml.nodes('//root/c') as records(email);
      

      【讨论】:

        【解决方案5】:

        这件作品我很久以前就遇到过。不能因为这项工作而受到任何赞扬,但这会很好地工作。

        CREATE FUNCTION [dbo].[fnSplitString] 
        ( 
        @string NVARCHAR(MAX), 
        @delimiter CHAR(1) 
        ) 
        RETURNS @output TABLE(splitdata NVARCHAR(MAX) 
        ) 
        BEGIN 
        DECLARE @start INT, @end INT 
        SELECT @start = 1, @end = CHARINDEX(@delimiter, @string) 
        WHILE @start < LEN(@string) + 1 BEGIN 
            IF @end = 0  
                SET @end = LEN(@string) + 1
        
            INSERT INTO @output (splitdata)  
            VALUES(SUBSTRING(@string, @start, @end - @start)) 
            SET @start = @end + 1 
            SET @end = CHARINDEX(@delimiter, @string, @start)
        
        END 
        RETURN 
        END
        
        
        select *from dbo.fnSplitString('joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com',';')
        

        【讨论】:

          【解决方案6】:

          我编写了这个我经常使用的函数...

          CREATE FUNCTION func_split(@value VARCHAR(8000), @delim CHAR)
          RETURNS
              @outtable TABLE (
                  i INTEGER,
                  value VARCHAR(1024)
              )
          AS
          BEGIN
              DECLARE @pos INTEGER
              DECLARE @count INTEGER
          
              IF LEN(@value) > 0
              BEGIN
                  SET @count = 1
                  SET @value = @value + @delim
                  SET @pos = CHARINDEX(@delim, @value, 1)
                  WHILE @pos > 0
                  BEGIN
                      INSERT INTO @outtable (i, value) VALUES (@count, LEFT(@value, @pos - 1))
                      SET @value = RIGHT(@value, LEN(@value) - @pos)
                      SET @pos = CHARINDEX(@delim, @value, 1)
                      SET @count = @count + 1
                  END
              END
          
              RETURN
          END
          

          然后你用...调用它

          DECLARE @emails AS TABLE (
              i INTEGER,
              value VARCHAR(1024)
          )
          
          INSERT INTO @split SEELCT * FROM func_split('joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com', ';');
          

          ...你最终会得到一个包含电子邮件地址的临时表,我是他们的输入顺序。

          【讨论】:

            【解决方案7】:

            最好的办法是将分隔字符串转换为柱状形式并从那里开始工作。

            你可以使用迭代方法,或者使用the Numbers table的方法(我更喜欢):

            declare 
                @list varchar(1000),
                @sep char(1)
            
            set @list = 'joebloggs@gmailcom;jimbowen@aol.com;dannybaker@msn.com';
            set @sep = ';'
            
            -- iterative method
            declare @res table (
                c varchar(100)
            )
            
            declare 
                @pos_start int,
                @pos_end int,
                @len_sep int,
                @exit int
            
            select @pos_start = 1, @pos_end = 1, @len_sep = len(@sep),  @exit = 0
            
            while @exit = 0
            begin
                set @pos_end = charindex(@sep, @list, @pos_start)
            
                if @pos_end <= 0 begin
                    set @pos_end = len(@list) + 1
                    set @exit = 1
                end
            
                insert @res(c) select substring(@list, @pos_start, @pos_end - @pos_start)
            
                set @pos_start = @pos_end + @len_sep
            end
            
            select * from @res
            
            -- the Numbers table method
            select substring(@list, n, charindex(@sep, @list + @sep, n) - n)
            from numbers 
            where substring(@sep + @list, n, 1) = @sep
            and n < len(@list) + 1
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-06-14
              • 1970-01-01
              • 2013-05-28
              • 2016-02-21
              • 1970-01-01
              • 2022-11-23
              • 2021-01-30
              相关资源
              最近更新 更多