拆分字符串后 returns a TABLE 的函数

Function which returns a TABLE after splitting a string

我想创建一个函数,其中 returns 一个 table 具有从输入字符串中提取的两列。

作为输入,该函数获取如下字符串:

'@Name=John;@Secondname=Kowalsky;@Mail=example@mail.com;'

该函数应该根据该字符串创建两列 - x、y。

X 表示 @value,Y 表示 =.

之后的值

我创建了这个:

Create FUNCTION TwoColumnsFromString (
    @ReplaceString varchar(max)
)
Returns @temptable TABLE (x varchar(max), y varchar(max))
AS 
BEGIN
    DECLARE @value1 varchar(max) 
    WHILE (LEN(@value1)) > 0
    BEGIN    
        SELECT  @value1 = (Select @ReplaceString)
        INSERT INTO @temptable (x,y)
        VALUES ((SUBSTRING(@ReplaceString, CHARINDEX('@', @ReplaceString), CHARINDEX('=',@ReplaceString) -CHARINDEX('@',@ReplaceString))),
            (SUBSTRING(@ReplaceString, CHARINDEX('=', @ReplaceString)+1, CHARINDEX(';',@ReplaceString) -CHARINDEX('=',@ReplaceString)-1)))

        SET @value1 = REPLACE(@value1, SUBSTRING(@value1, 1, CHARINDEX(';', @value1)), '')
    END
    RETURN
END
GO

SELECT *
FROM TwoColumnsFromString('@Name=John;@Secondname=Kowalsky;@Mail=example@mail.com;')

但是 returns 一个空的 table。我在这里做错了什么?

你失去了上一个问题的所有好工作:)

  1. 您应该将 @value1 的起始值分配给 在您的循环 之外
  2. 您的插入计算现在应该引用 @value1

你的函数体应该是

    BEGIN
      -- Set starting value outside the loop
      DECLARE @value1 VARCHAR(max) = @ReplaceString;

      WHILE (LEN(@value1)) > 0
      BEGIN
          -- We are now using @value1 not @ReplaceString
          INSERT INTO @temptable (x,y)
          VALUES ((SUBSTRING(@value1, CHARINDEX('@', @value1), CHARINDEX('=',@value1) -CHARINDEX('@',@value1))),
                  (SUBSTRING(@value1, CHARINDEX('=', @value1)+1, CHARINDEX(';',@value1) -CHARINDEX('=',@value1)-1)));

          SET @value1 = REPLACE(@value1, SUBSTRING(@value1, 1, CHARINDEX(';', @value1)), '');
      END
      RETURN;
    END

为什么不尝试这样的事情呢?

create function [dbo].[fn_GetKeyValuePairs](
    @ReplaceString nvarchar(max)
)
returns table
as return (
    select Left(a.[value], (CharIndex(N'=', a.[Value]) - 1)) as [Key]
         , Right(a.[value], (Len(a.[value]) - CharIndex(N'=', a.[Value]))) as [Value]
    from String_Split(Left(@ReplaceString, Len(@ReplaceString) - CharIndex(N';', Right(@ReplaceString, 1))), N';') as a
);

工作函数:

ALTER FUNCTION MailReplacer20 (
@ReplaceString varchar(max)
)
Returns @temptable TABLE (x varchar(max), y varchar(max))
AS 
BEGIN
DECLARE @value1 varchar(max) = @replacestring
WHILE (LEN(@value1)) > 0

    BEGIN
    INSERT INTO @temptable (x,y)
    VALUES ((SUBSTRING(@value1, CHARINDEX('@', @value1), CHARINDEX('=',@value1) -CHARINDEX('@',@value1))),
            (SUBSTRING(@value1, CHARINDEX('=', @value1)+1, CHARINDEX(';',@value1) -CHARINDEX('=',@value1)-1)))

    SET @value1 = REPLACE(@value1, SUBSTRING(@value1, 1, CHARINDEX(';', @value1)), '')
    END
RETURN
END
GO

我有一个不同的策略,没有循环并使用自 2016 年以来在 SQL 服务器中可用的 STRING_SPLIT 函数。

我的想法是将一个拆分为结构,将另一个拆分为函数,因为它有两个分隔符。

  1. 实现一个名为SplitValue的标量函数如下

    CREATE FUNCTION SplitValue
    (
        @Info as varchar(4000),
        @position as int=1,
        @separator as char
    )
    RETURNS varchar(8000)
    AS 
    BEGIN
        declare @Returnvalue as varchar(4000);
        with DataList as
        (
            SELECT ROW_NUMBER() OVER(ORDER BY value ) AS ID,value as Returnvalue 
            FROM STRING_SPLIT(@Info, @separator)
        )
        select @Returnvalue= isnull(Returnvalue,'')
        from DataList
        where ID = @position
        RETURN @Returnvalue;
    END;
    go
    
  2. 从查询中调用此函数

    declare @InfoALL as varchar(4000) = '@Name=John;@Secondname=Kowalsky;@Mail=example@mail.com;';
    declare @position as int = 1
    declare @position2 as int = 2
    declare @separator as char = '='
    
    SELECT 
        ROW_NUMBER() OVER(ORDER BY value ) AS ID,
        value,
        dbo.SplitValue(value,1,'=') AS Name,
        dbo.SplitValue(value,2,'=') AS Name
    FROM STRING_SPLIT(@InfoALL, ';')
    where value <> ''
    go
    

Example