Sql server TSQL-将分隔字符串拆分为列 问题

Sql server TSQL-将分隔字符串拆分为列 问题,sql-server,sql-server-2008,ssis,ssis-2008,Sql Server,Sql Server 2008,Ssis,Ssis 2008,我有许多文件名字符串,我想使用tilda作为分隔符将它们解析为列。字符串采用静态格式: Filepath示例C:\My Documents\PDF 姓氏示例Walker 名字示例Thomas 出生日期示例19991226 文档创建日期时间示例20180416150322 文档扩展示例.pdf 因此,完整的串联示例如下所示: C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf SELECT Surname = --del

我有许多文件名字符串,我想使用tilda作为分隔符将它们解析为列。字符串采用静态格式:

  • Filepath示例
    C:\My Documents\PDF
  • 姓氏示例
    Walker
  • 名字示例
    Thomas
  • 出生日期示例
    19991226
  • 文档创建日期时间示例
    20180416150322
  • 文档扩展示例
    .pdf
因此,完整的串联示例如下所示:

C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf
SELECT Surname = --delimitedString[0]
       FirstName = --delimitedString[1]
       --etc.
我想忽略字符串中给定的文件路径和扩展名,只将以下值解析为列:

  • 姓氏、名字、出生日期、文档创建日期时间
比如:

C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf
SELECT Surname = --delimitedString[0]
       FirstName = --delimitedString[1]
       --etc.

我试过的 我知道为了分割字符串,我需要执行几个任务,首先我需要修剪扩展名和文件路径,以便返回以tildas(~)分隔的字符串

这对我来说是一个问题,但是问题2是拆分新删除的字符串本身,即

Walker~Thomas~19991226~20180416150322
我已经很好地阅读了这篇非常全面的文章,似乎(因为我使用的是SQL Server 2008R2),唯一的选择是使用带有循环或递归CTE的函数,或者尝试使用
SUBSTRING()
charIndex()
进行非常混乱的尝试

我知道如果我有权访问SQL Server 2016,我可以使用
string\u split
,但不幸的是我无法升级


我确实可以访问SSI,但我对它非常陌生,因此决定尝试在SQL语句中完成大部分工作

我知道您提到过,如果可能的话,我希望避免使用
charindex()
选项,但我希望以一种半可读的方式解决了这个问题。当我将每个参数分隔在不同的行上并使用缩进级别时,我发现阅读这样的复杂函数有点容易。这不是最合适的外观,但有助于清晰易读:

with string as (select 'C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf' as filepath)

select 
    substring(
        filepath,
        len(filepath)-charindex('\',reverse(filepath))+2,           --start location, after last '\'
        len(filepath)-                                              --length of path
            (len(filepath)-charindex('\',reverse(filepath))+2)-         --less characters up to last '\'
            (len(filepath)-charindex('.',filepath))                     --less file extention
        )
from string

这里有一个没有拆分器的方法,应该不会太复杂

declare @var table (filepath varchar(256))
insert into @var values
('C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf')


;with string as(
select 
    x = right(filepath,charindex('\',reverse(filepath))-1) 
    from @var
)

select
    SurName= substring(x,1,charindex('~',x) - 1)
    ,FirstName = substring(x,charindex('~',x) + 1,charindex('~',x) - 1)
from string

弗里茨已经有了一个很好的开始,我的答案只是再加上它

with string as (select 'C:\My Documents\PDF\Walker~Thomas~19991226~20180416150322.pdf' as filepath)
, newstr as (
select 
    REPLACE(substring(
        filepath,
        len(filepath)-charindex('\',reverse(filepath))+2,           --start location, after last '\'
        len(filepath)-                                              --length of path
            (len(filepath)-charindex('\',reverse(filepath))+2)-         --less characters up to last '\'
            (len(filepath)-charindex('.',filepath))                     --less file extention
        ) , '~', '.') as new_part
from string
)
SELECT
      PARSENAME(new_part,4) as Surname,
      PARSENAME(new_part,3) as [First Name],
      PARSENAME(new_part,2) as [Birth Date], 
      PARSENAME(new_part,1) as [Document Created Datetime]
FROM newstr

不要使用那个代码。它的性能不好。这两个博客将为您提供更好的服务。为什么要在TSQL中执行此操作,而不是在C#或Java或类似的东西中执行此操作?这样做更合适、更容易。charIndex()在代码长度之外有什么问题?这似乎是最合理的选择。@scsimon感谢您提供的链接,我现在将通读它们。@Fritz我担心子字符串()和CharIndex()会很快变成无法阅读的代码。如果这是我唯一的选择,那么我想我必须探索这条路,但现在我愿意接受建议。谢谢弗里茨,在这条路上走了一段路。这将提供不带文件路径和扩展名的分隔字符串。现在我只需要解析分隔的字符串哦,哎呀。我完全忘记了按瓷砖分割的部分。在每个可能的数据段中是否有一致数量的波浪形字符,或者是否有所不同?始终有四个部分:姓氏、名字、出生日期、文档创建日期感谢Fritz,我将同意你的回答,因为这是一个很好的开始,随后是EricZ的继续。干得好。我感谢你们所有人的帮助,并将听取西蒙斯关于东西性能方面的建议。相反,东西往往很贵,但字符串不是很长,所以这很好。@scsimon谢谢你们的例子,在这三个答案中,我只是想知道哪一个在大一点的车上最便宜dataset@MasterYoda唯一的判断方法是在环境中的同一数据集上分别运行它们并记录时间。我们也可以这样做,但我们需要一个现实的数据集。此外,通过我设置的链接拆分字符串可能仍然是最好的方法。如果您选择基准点,请确保每次都使用一个新的计划,而不是一个可以加速连续运行的缓存版本。此外,请记住,如果是毫秒之间的参数,甚至是几秒钟之间的参数,则差异可能在于我们大多数人使用的
CTE
,这可以通过使用临时表或派生表来加速。请务必检查查询计划,如果您对此有疑问,以及为什么一个比另一个更快,我会将其发布在dba.stackexchange.com上,并确保通过@scsimon添加您的查询计划。这是100%正确的,我想明天我必须在更大的数据集上单独测试每个查询计划。感谢您的时间和建议,非常感谢。parsename:)+1的用法很好