【问题标题】:What is the most performant method for splitting strings?分割字符串最高效的方法是什么?
【发布时间】:2026-02-22 10:40:01
【问题描述】:

代码

create table ExampleTable
(
    Name varchar(500)
    CultureCode(5)
)

insert into ExampleTable values('Dit is een test', 'nl-NL')
insert into ExampleTable values('This is a test', 'en-GB')
insert into ExampleTable values('Ceci est un test', 'fr-FR')
insert into ExampleTable values('Dies ist ein Test', 'de-DE')

create procedure GetNameByCultures
(
@CultureCodes varchar(250)
)
as 
begin
//Get ExampleTable items according to the culture codes stated in @CultureCodes
end

-示例:

CREATE TYPE StringListType AS TABLE
(
    [str] varchar(5) NULL
)

我正在使用 MS SQL 2012 V11.0.2100.60

情况

我正在尝试找到提取标签的最佳方法(性能方面)。 我想过但尚未测试的方法是:

  • 如上所示创建用户定义的表类型。

优点:我知道它在数据库上几乎没有性能。

缺点:我必须在存储过程中添加另一个参数。

  • 创建一个按字符分割字符串的函数:','

缺点:我知道在 SQL 中使用“Right”、“Left”、“Like”和其他 varchar 转换/编辑属性很慢

UpSide:我可以将处理保存在数据库中。

在当前情况下,我只在用户定义的表类型中发送一个文化代码。 因此,无法在此 UDTT 中添加文化代码,因为您无法将 UDTT 添加到 UDTT。 我唯一的选择是向存储过程添加另一个参数,这应该不是什么大问题……但我们希望只保留一个。

有没有人碰巧知道另一种(更好的?)方法,或者我应该使用其中一种方法吗?

【问题讨论】:

  • 哪种风格的数据库?我假设 [sql] 您的意思是 MS SQL Server。如果是这样,请说出来。并包括版本号。性能和可用技术的范围可能会因您使用的版本而异。
  • 使用MS SQL 2012 V11.0.2100.60
  • 表值参数是您使用 2008 年以后的最佳方式。阅读these very thorough articles,了解可用的不同方法,以及分析和性能详细信息。
  • @TheunArbeider 我已按要求发布了评论作为答案:-)

标签: sql-server performance sql-server-2012 string-split


【解决方案1】:

表值参数是您使用 2008 年以后的最佳方式。 (See MSDN)。

我强烈建议您阅读 SQL Server MVP Erland Sommarskog 关于可用不同方法的非常全面的文章,其中包含分析和性能详细信息。

【讨论】:

    【解决方案2】:

    我仍然会将文化列表作为逗号分隔的字符串传递,定义一个返回表的函数,然后将该表连接到您的示例表。只要字符串包含少量元素,您就不会注意到任何性能下降。

    如果你能忍受通过最多 N 个文化代码的限制,你可以尝试这样的事情

    create procedure GetNameByCulture 
      @CultureInfo varchar(5),
      @CultureInfo1 varchar(5) = null,
      @CultureInfo2 varchar(5) = null
    as
     select e.* 
       from ExampleTable e 
            join (
              select @CultureInfo as CultureInfo union
              select @CultureInfo1 union
              select @CultureInfo2
              ) x 
              on e.CultureInfo = x.CultureInfo
    

    我猜这会比字符串版本快一点。但正如我所提到的,无论如何这也没什么大不了的。

    【讨论】:

    • 在示例中,我只使用了 4 个翻译。但我可能是将来我们将有 30 或 40 个翻译......那么它仍然没有问题吗?
    • 如果你使用这种方法(即有 30-40 个可选参数)没有。就个人而言,我不喜欢这种解决方案,从美学的角度来看,它似乎是“丑陋的”(“代码美观”)。但这只是我个人的看法。但如果性能是您的问题,为什么不直接实现这三种方法(字符串、表格和可选参数)并进行一些测试?
    【解决方案3】:

    如何使用替换和转换为 xml 而不是左/右拆分字符串?

        declare @ExampleTable table
        (
            Name varchar(500),
            CultureCode varchar(5)
        )
    
        insert into @ExampleTable values('Dit is een test', 'nl-NL')
        insert into @ExampleTable values('This is a test', 'en-GB')
        insert into @ExampleTable values('Ceci est un test', 'fr-FR')
        insert into @ExampleTable values('Dies ist ein Test', 'de-DE')
    
    
        declare @CultureCodes varchar(250)
        set @CultureCodes = 'nl-NL,en-GB,fr-FR'
    
        declare @xml xml
        set @xml = cast('<culturecodes><culture>'+REPLACE(@CultureCodes,',','</culture><culture>')+'</culture></culturecodes>' as xml)
    
        select 
               C.element.value('.','varchar(max)') as CultureCode_splited
              ,E.CultureCode 
              ,E.name
        from @xml.nodes('/culturecodes/culture')C(element)
        inner join @ExampleTable E
        on E.CultureCode = C.element.value('.','varchar(max)')
    

    结果集看起来像这样......

        CultureCode_splited     CultureCode name
        nl-NL                   nl-NL       Dit is een test
        en-GB                   en-GB       This is a test
        fr-FR                   fr-FR       Ceci est un test
    

    【讨论】:

    • 我不确定是否要替换.. 但我被告知并有经验,SQL 中的任何字符串更改方法都会以性能为代价,而性能是我们的首要任务!