SQL – Séparer le text de la string

J'ai une table (dans SQL Server) qui a 2 colonnes. Une colonne contient plusieurs noms de servers séparés par un tilda ~ . Cette colonne peut ou ne peut pas contenir le nom du server réel. L'autre colonne a le nom du server réel.

Je cherche un moyen de séparer les valeurs de la première colonne dans leur propre colonne séparée. Le nombre d'alias va de 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 

J'ai les deux premiers servers extraits de la string, j'ai des problèmes sur les prochains. Toute aide est appréciée !!!

 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 

La façon la plus simple d'y parvenir est d'utiliser un séparateur de strings. Aaron Bertrand a une list assez complète d'options viables ici. http://sqlperformance.com/2012/07/t-sql-queries/split-ssortingngs . Notez qu'aucun d'entre eux n'a de loops ou de récursivité. Je ne suis pas sûr de ce que vous essayez de faire avec cette information, mais vous avez déclaré que vous vouliez juste parsingr les strings.

 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 

Vous pouvez également enlever ~ extra de la fin si vous voulez, mais je pense que cela fonctionnera même si vous ne le faites pas.

@Hogan – J'ai fini par combiner votre script avec l'aide du lien que @Sean Lange a mis dans son commentaire. Voici ce que j'ai trouvé.

 WITH splitit AS ( SELECT yivalue('(./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, --yivalue('(./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