如何使用T-SQL使用分隔符char分割字符串?

时间:2011-02-23 20:23:03

标签: sql sql-server sql-server-2005 tsql

我在表格的一列中有这个长字符串。我只想获得具体信息: - 我的表结构: -

Col1 = '123'
Col2 = 'AAAAA'
Col3 = 'Clent ID = 4356hy|Client Name = B B BOB|Client Phone = 667-444-2626|Client Fax = 666-666-0151|Info = INF8888877 -MAC333330554/444400800'

我的选择陈述是: -

Select col1, col2, col3 from Table01

但是在Col3中,我只需要'客户名称'的值'B B BOB'。

在Col3中 -

  • 列分隔符为'|' pipe char(例如'Client ID = 4356hy')

  • 键值分隔符'='等于带有一个空格(前导和尾随)的符号。

请帮忙。

4 个答案:

答案 0 :(得分:9)

对于您的特定数据,您可以使用

Select col1, col2, LTRIM(RTRIM(SUBSTRING(
    STUFF(col3, CHARINDEX('|', col3,
    PATINDEX('%|Client Name =%', col3) + 14), 1000, ''),
    PATINDEX('%|Client Name =%', col3) + 14, 1000))) col3
from Table01

编辑 - charindex与patindex

测试

select col3='Clent ID = 4356hy|Client Name = B B BOB|Client Phone = 667-444-2626|Client Fax = 666-666-0151|Info = INF8888877 -MAC333330554/444400800'
into t1m
from master..spt_values a
cross join master..spt_values b
where a.number < 100
-- (711704 row(s) affected)

set statistics time on

dbcc dropcleanbuffers
dbcc freeproccache
select a=CHARINDEX('|Client Name =', col3) into #tmp1 from t1m
drop table #tmp1

dbcc dropcleanbuffers
dbcc freeproccache
select a=PATINDEX('%|Client Name =%', col3) into #tmp2 from t1m
drop table #tmp2

set statistics time off

计时

CHARINDEX:

 SQL Server Execution Times (1):
   CPU time = 5656 ms,  elapsed time = 6418 ms.
 SQL Server Execution Times (2):
   CPU time = 5813 ms,  elapsed time = 6114 ms.
 SQL Server Execution Times (3):
   CPU time = 5672 ms,  elapsed time = 6108 ms.

PATINDEX:

 SQL Server Execution Times (1):
   CPU time = 5906 ms,  elapsed time = 6296 ms.
 SQL Server Execution Times (2):
   CPU time = 5860 ms,  elapsed time = 6404 ms.
 SQL Server Execution Times (3):
   CPU time = 6109 ms,  elapsed time = 6301 ms.

结论

700k调用的CharIndex和PatIndex的时间在彼此的3.5%之内,所以我认为无论使用哪个都不重要。当两者都可以工作时,我可以互换使用它们。

答案 1 :(得分:3)

您需要分割功能:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create Function [dbo].[udf_Split]
(   
    @DelimitedList nvarchar(max)
    , @Delimiter nvarchar(2) = ','
)
RETURNS TABLE 
AS
RETURN 
    (
    With CorrectedList As
        (
        Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            + @DelimitedList
            + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End
            As List
            , Len(@Delimiter) As DelimiterLen
        )
        , Numbers As 
        (
        Select TOP( Coalesce(DataLength(@DelimitedList)/2,0) ) Row_Number() Over ( Order By c1.object_id ) As Value
        From sys.columns As c1
            Cross Join sys.columns As c2
        )
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position
        , Substring (
                    CL.List
                    , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen     
                    , CharIndex(@Delimiter, CL.list, N.Value + 1)                           
                        - ( CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen ) 
                    ) As Value
    From CorrectedList As CL
        Cross Join Numbers As N
    Where N.Value <= DataLength(CL.List) / 2
        And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter
    )

使用split功能,您可以使用Cross Apply来获取数据:

Select T.Col1, T.Col2
    , Substring( Z.Value, 1, Charindex(' = ', Z.Value) - 1 ) As AttributeName
    , Substring( Z.Value, Charindex(' = ', Z.Value) + 1, Len(Z.Value) ) As Value
From Table01 As T
    Cross Apply dbo.udf_Split( T.Col3, '|' ) As Z

答案 2 :(得分:0)

你只需要在col3 ....中的字符串上做一个SUBSTR。

    Select col1, col2, REPLACE(substr(col3, instr(col3, 'Client Name'), 
    (instr(col3, '|', instr(col3, 'Client Name')  -
    instr(col3, 'Client Name'))
    ),
'Client Name = ',
'')
    from Table01 

是的,由于原始问题中所述的原因,这是一个糟糕的数据库设计

答案 3 :(得分:0)

太可怕了,但你可以尝试使用

select
SUBSTRING(Table1.Col1,0,PATINDEX('%|%=',Table1.Col1)) as myString
from
Table1

这段代码可能不是100%正确。需要调整