sql-server - 是否有一个 SQL 函数可以将固定宽度的分隔字符串拆分为一个表,每个值对应一行?

标签 sql-server tsql

我需要能够拆分以逗号分隔的固定宽度字符串列表。在一个特定情况下,我需要拆分 8 个字符的十六进制 PIN 码列表。其他目标是比 SO 和 Internet 上大量使用的通用 SQL 拆分函数具有更高性能的函数,以及用户友好的语法,例如:

declare @pinList varchar(max)
set @pinList = 'D1D57EFD,9917D94B,0687E581,C6AA229E,044B136B,ED90E4AF,143E23FB,DF5CF1CB,D711F644,67138659'

select *
from fixedWidthSplitFunction(@list, 8, ',')

最佳答案

这是一个特殊用途、固定宽度、定界字符串、表值拆分函数(好吧,那是一口):

create function tvfFixedWidthSplitter
(
    @stringList varchar(max),
    @fixedWidth int,
    @delimiter varchar(10)
)
returns @strings table
(
    id int,
    string varchar(max)
)
as

begin

    with buckets as
    (   
        select 1 id

        union all

        select t.id + 1
        from buckets t
        where id = t.id 
            and t.id < len(@stringList)/(@fixedWidth+len(@delimiter))+1
    )

    insert into @strings
    select 
        id, 
        substring(@stringList, ((id - 1) * (@fixedWidth + len(@delimiter)) + (case when len(@delimiter)-1 = 0 then len(@delimiter) else len(@delimiter)-(len(@delimiter)-1) end)), @fixedWidth) string
    from buckets    
    option (maxrecursion 0)

    return;

end

示例用法

select *
from tvfFixedWidthSplitter('D1D57EFD,9917D94B,0687E581,C6AA229E,044B136B,ED90E4AF,143E23FB,DF5CF1CB,D711F644,67138659', 8, ',')

因为它的域是固定宽度的分隔字符串,所以它包括在大多数通用拆分函数中不可能实现的优化。在我的测试中,它优于我遇到的所有其他通用字符串拆分函数,当该函数用于与物理表的 JOIN 时,例如:

select u.UserName
from Users u
join tvfFixedWidthSplitter(@pinList, 8, ',') s
    on u.Pin = s.string

关于sql-server - 是否有一个 SQL 函数可以将固定宽度的分隔字符串拆分为一个表,每个值对应一行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25669780/

相关文章:

sql-server - 用于确定标量函数的返回类型的 SQL 查询

sql - 为什么我必须在插入超过 150,000 条记录后重建表的索引?

tsql - T-SQL列名称中允许使用哪些特殊字符?

sql - 没有存储过程的错误返回

SQL Server 字符串搜索和评估

sql-server - 如何使用 IN 运算符整理 SQL_Latin1_General_CP1_CI_AS

sql - 您可以设置自动增量将达到的最大值吗

sql-server - 时间历史表中的重复项

c# - 如何从 C# 连接到 SQL 数据库?

sql - “数据库可能尚未激活或可能正在转换”错误