【问题标题】:Function which returns a TABLE after splitting a string拆分字符串后返回 TABLE 的函数
【发布时间】:2020-07-19 00:20:42
【问题描述】:

我想创建一个函数,它返回一个表,其中包含从输入字符串中提取的两列。

作为输入,函数得到如下字符串:

'@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;')

但这会返回一个空表。我在这里做错了什么?

【问题讨论】:

  • WHILE 循环永远不会执行,因为@value1 为空,只是声明了。
  • 这有帮助!谢谢!

标签: sql sql-server replace substring charindex


【解决方案1】:

您在上一个问题中失去了所有出色的工作:)

  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

【讨论】:

  • 是的,我在评论后做了更改:“WHILE 循环永远不会执行,因为@value1 为空,只声明了。”但是......“你从上一个问题中失去了所有的好工作:)” - 很痛! :D
【解决方案2】:

为什么不试试这样的东西呢?

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
);

【讨论】:

  • SQL Server 2016+
  • 你用'@Name=John;@Secondname=Kowalsky;@Mail=example@mail.com;'测试了吗?
  • Ops "传递给 LEFT 或 SUBSTRING 函数的长度参数无效。"
  • @Sami 我做了,并故意省略了处理特定边缘情况的逻辑,因为问题有很多解决方案;其中大部分都是显而易见的和微不足道的。已通过此类处理的示例更新了答案,以安抚花生画廊。
  • @DaleK 是的,这就是我问他的意思,这段代码不会将le@mail 中的@ 计入计数。
【解决方案3】:

工作功能:

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

【讨论】:

    【解决方案4】:

    我有一个不同的策略,没有循环,并使用自 2016 年以来在 SQL Server 中可用的 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-13
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      • 2010-12-22
      相关资源
      最近更新 更多