SQL - 从字符串

时间:2016-03-09 21:44:12

标签: sql sql-server substring

我有一个包含2列的表(在SQL Server中)。一列包含使用tilda ~分隔的多个服务器名称。此列可能包含也可能不包含实际的服务器名称。另一列具有实际的服务器名称。

我正在寻找一种方法将第一列值分成它们自己的分隔列。别名的数量范围从1到?。

Server_Alias_Names                              Actual_Server_Name
------------------------------------------------------------
Server1~ROSCO24~Server3~Server4~~~~~            ROSCO24
STEVETESDB26~~~~~~~~~                           STEVETESDB26
RALPHPRD117~RALPHPRD117-adm~Server0025~Server0025a1~Server0025a2~Server0025a3~~~~~        RALPHPRD117
Server1001~Server1001R1~Server1001-adm~~~~~~~   DBTEST1001

我从字符串中提取了前两个服务器,我在接下来的几个服务器上遇到了麻烦。任何帮助表示赞赏!!!

SELECT
    LEFT(Server_Alias_Names, CHARINDEX('~', Server_Alias_Names) - 1) as 'First_Server',
SUBSTRING(Server_Alias_Names,len(LEFT(Server_Alias_Names, CHARINDEX('~', Server_Alias_Names)+1)),LEN(LEFT(Server_Alias_Names, CHARINDEX ('~', Server_Alias_Names)))) as 'Second_Server'
FROM 
    TBL_NAME

3 个答案:

答案 0 :(得分:3)

实现这一目标的最简单方法是使用字符串拆分器。 Aaron Bertrand在这里提供了相当完整的可行选项列表。 http://sqlperformance.com/2012/07/t-sql-queries/split-strings。请注意,这些都没有任何循环或递归。我不太确定你要对这些信息做什么,但你说你只想解析字符串。

答案 1 :(得分:1)

WITH splitit
AS
(
    SELECT Actual_Server_Name,  len(Actual_Server_Name) - len(replace(Actual_Server_Name, '~', '')) as TildaCount,
    CONVERT(XML,'<X><x>'  
    + REPLACE(Server_Alias_Names,'~', '</x><x>') + '</x></X>') AS xmlname
      FROM table
)
SELECT Actual_Server_Name,      
       CASE TildaCount > 0 THEN xmlname.value('/X/x[1]','varchar(100)') ELSE '' END AS s1,    
       CASE TildaCount > 1 THEN xmlname.value('/X/x[2]','varchar(100)') ELSE '' END AS s2,    
       CASE TildaCount > 2 THEN xmlname.value('/X/x[3]','varchar(100)') ELSE '' END AS s3,    
       CASE TildaCount > 3 THEN xmlname.value('/X/x[4]','varchar(100)') ELSE '' END AS s4,    
       CASE TildaCount > 4 THEN xmlname.value('/X/x[5]','varchar(100)') ELSE '' END AS s5,    
       CASE TildaCount > 5 THEN xmlname.value('/X/x[6]','varchar(100)') ELSE '' END AS s6,    
       CASE TildaCount > 6 THEN xmlname.value('/X/x[7]','varchar(100)') ELSE '' END AS s7
FROM splitit

如果你愿意,你也可以从最后删除额外的〜,但我认为即使你不这样做也会有效。

答案 2 :(得分:0)

@Hogan - 我最终将你的脚本与@Sean Lange在评论中提供的链接中的一些帮助结合起来。这就是我想出来的。

WITH splitit
AS
(
SELECT 
y.i.value('(./text())[1]', 'nvarchar(4000)') as Separated_Server,
Actual_Server_Name
FROM 
          ( 
            SELECT x = CONVERT(XML, '<i>' 
            + REPLACE(Server_Alias_Names,'~', '</i><i>') 
            + '</i>').query('.')
            , Actual_Server_Name
            FROM TBL_NAME
          ) as a cross apply x.nodes('i') as y(i)
)

SELECT DISTINCT
Actual_Server_Name,
Separated_Server
FROM splitit
Where Separated_Server is not null
ORDER BY 1,2

--Some of the separated items were also sorted by a comma so I added another step to separate those as well.
--Uncomment the code below for an additional and replace the comma after Separated_Server with the special character you want to use for separation

--,splitit_2
--AS
--(
--SELECT distinct
--ServerName,
--y.i.value('(./text())[1]', 'nvarchar(4000)') as Server_Alias

--FROM 
--          ( 
--          SELECT x = CONVERT(XML, '<i>' 
--          + REPLACE(Separated_Server,',', '</i><i>') 
--          + '</i>').query('.')
--          ,[ServerName]
--          FROM splitit
--        ) as a cross apply x.nodes('i') as y(i)
--)


--SELECT DISTINCT
--Actual_Server_Name,
--Separated_Server
--FROM splitit_2
--Where Separated_Server is not null
--ORDER BY 1,2