【问题标题】:SQL Server: Splitting string by '/' and put each split element into a different columnSQL Server:用'/'分割字符串并将每个分割元素放入不同的列
【发布时间】:2013-05-23 19:29:01
【问题描述】:

我在外部站点上有一个表,需要将其复制到本地数据库,但需要进行一些转换。我必须大量修改的列之一称为 product_url。 URL 的格式为 site.com\category\sub-category\brand\model#。

我本地数据库中的表将有 4 列来保存这些数据。它们将是类别、子类别、品牌和型号#。因此,我必须先修剪 site.com(我使用 truncate 进行了此操作),但现在我必须解析 \category\sub-category\brand\model#

我从 SO 中找到了一个我认为会有所帮助的 UDF。这里是:

create function dbo.SplitString 
    (
        @str nvarchar(4000), 
        @separator char(1)
    )
    returns table
    AS
    return (
        with tokens(p, a, b) AS (
            select 
                1, 
                1, 
                charindex(@separator, @str)
            union all
            select
                p + 1, 
                b + 1, 
                charindex(@separator, @str, b + 1)
            from tokens
            where b > 0
        )
        select
            p-1 zeroBasedOccurance,
            substring(
                @str, 
                a, 
                case when b > 0 then b-a ELSE 4000 end) 
            AS s
        from tokens
      )
    GO

现在我无法使用此功能。可能是因为我缺乏使用 UDF 的经验。

这是我现在拥有的:

select s from
dbo.SplitString(select substring(product_url, 8, len(product_url)) 
            from Products, '/')
where zeroBasedOccurance=0 AS Category

这显然甚至在语法上都不正确。

我想知道我是否是最好的方法。我还不是 DBA,所以我很难解决这个问题。我只需要弄清楚如何为 product_url 表中的每一行应用此 UDF 约 4 次。

【问题讨论】:

    标签: sql sql-server split sql-server-2000


    【解决方案1】:

    不确定你的功能,但这是我的:

    CREATE FUNCTION dbo.FN_PARSENAME(@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
    

    你这样称呼它:
    SELECT Address_Line1 = dbo.fn_Parsename(Merged,'|', 0) FROM Table

    其中 Merged 是分隔的字段,'|'是分隔符,所以你可以把它设为'\',0是你想要的字符串的哪一部分,0是第一个,向上。

    对于您的示例,它将是:

    SELECT category = dbo.fn_Parsename(product_url,'\', 1)
         , sub-category = dbo.fn_Parsename(product_url,'\', 2)
         , brand = dbo.fn_Parsename(product_url,'\', 3)
         , model# = dbo.fn_Parsename(product_url,'\', 4)
    FROM Table 
    

    或者可能是 0-3,具体取决于。

    我很有信心我是根据我发现的东西改编的,甚至可能是在 SO 上,但我不记得谁值得称赞。

    【讨论】:

    • 太棒了!感谢您的解决方案。对于遇到此问题并分享不得不使用 SQL 200m0 的不幸的任何其他人,请注意,您不能使用默认值声明变量。因此,只需在声明后设置它们即可。
    • 啊,好点子,希望那是一小群人。如果这就是你所需要的,请接受这个作为答案。
    • 我们只能希望。我打算,只需要等待它允许我。
    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 2019-01-12
    • 1970-01-01
    • 2020-07-04
    • 2011-03-26
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多