J'ai une colonne SQL Server 2008 R2 contenant une chaîne que je dois diviser par une virgule. J'ai vu de nombreuses réponses sur StackOverflow mais aucune d'elles ne fonctionne dans R2. Je me suis assuré de disposer des autorisations de sélection sur tous les exemples de fonction fractionnée. Toute aide grandement appréciée.
sql
sql-server
tsql
sql-server-2008
split
Lee Grindon
la source
la source
mdq.RegexSplit
fonction dans le module complémentaire "Master Data Services", qui peut vous aider. Il vaut certainement la peine d'enquêter .Réponses:
J'ai déjà utilisé ce SQL qui peut fonctionner pour vous: -
et pour l'utiliser: -
la source
Au lieu de CTE récursifs et de boucles while, quelqu'un a-t-il envisagé une approche plus basée sur les ensembles? Notez que cette fonction a été écrite pour la question, qui était basée sur SQL Server 2008 et la virgule comme délimiteur . Dans SQL Server 2016 et supérieur (et au niveau de compatibilité 130 et supérieur),
STRING_SPLIT()
est une meilleure option .Si vous souhaitez éviter que la longueur de la chaîne soit limitée à <= le nombre de lignes dans
sys.all_columns
(9,980 dansmodel
SQL Server 2017; beaucoup plus élevé dans vos propres bases de données utilisateur), vous pouvez utiliser d'autres approches pour dériver les nombres, telles que construire votre propre table de nombres . Vous pouvez également utiliser un CTE récursif dans les cas où vous ne pouvez pas utiliser de tables système ou créer les vôtres:Mais vous devrez ajouter
OPTION (MAXRECURSION 0)
(ouMAXRECURSION <longest possible string length if < 32768>
) à la requête externe afin d'éviter les erreurs de récursivité pour les chaînes> 100 caractères. Si ce n'est pas non plus une bonne alternative, voyez cette réponse comme indiqué dans les commentaires.(En outre, le délimiteur devra être
NCHAR(<=1228)
. Je recherche toujours pourquoi.)Plus d'informations sur les fonctions de fractionnement, pourquoi (et la preuve que) alors que les boucles et les CTE récursifs ne sont pas mis à l'échelle, et de meilleures alternatives, si les chaînes de fractionnement provenant de la couche d'application:
la source
sys.all_objects
est inférieur au nombre de caractères dans la chaîne d'entrée, elle tronquera la chaîne et les valeurs disparaîtront. Comme ilsys.all_objects
est simplement utilisé comme un hack pour générer des lignes, il existe de meilleures façons de le faire, par exemple cette réponse .Enfin, l'attente est terminée dans SQL Server 2016, ils ont introduit la fonction de chaîne de fractionnement:
STRING_SPLIT
Toutes les autres méthodes pour diviser une chaîne comme XML, table Tally, boucle while, etc. ont été époustouflées par cela
STRING_SPLIT
fonction.Voici un excellent article avec une comparaison des performances: Surprises et hypothèses de performances: STRING_SPLIT
la source
Le moyen le plus simple de le faire est d'utiliser le
XML
format.1. Conversion de chaîne en lignes sans tableau
REQUETE
RÉSULTAT
2. Conversion en lignes d'une table avec un ID pour chaque ligne CSV
TABLEAU DES SOURCES
REQUETE
RÉSULTAT
la source
@String
contient des caractères interdits ... Je viens de poster une réponse pour surmonter ce problème.Je avais besoin d' un moyen rapide de se débarrasser du à
+4
partir d' un code postal .Pas de proc ... pas d'UDF ... juste une petite commande en ligne serrée qui fait ce qu'il faut. Pas de fantaisie, pas élégant.
Changez le délimiteur si nécessaire, etc., et cela fonctionnera pour tout.
la source
si vous remplacez
avec
vous pouvez éliminer ce dernier insert après la boucle while!
la source
+1
deSELECT @pos = LEN(@stringToSplit)
semble résoudre ce problème. Cependant, leSELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
retourne àInvalid length parameter passed to the LEFT or SUBSTRING function
moins que vous ajoutiez également+1
au troisième paramètre de SUBSTRING. ou vous pouvez remplacer cette affectation parSET @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, 4000) --MAX len of nvarchar is 4000
Toutes les fonctions de fractionnement de chaînes qui utilisent une sorte de boucle (itérations) ont de mauvaises performances. Ils doivent être remplacés par une solution basée sur des ensembles.
Ce code s'exécute parfaitement.
la source
@List
contient des caractères interdits ... Je viens de poster une réponse pour surmonter ce problème.L'approche souvent utilisée avec les éléments XML se rompt en cas de caractères interdits. C'est une approche pour utiliser cette méthode avec n'importe quel type de caractère, même avec le point-virgule comme délimiteur.
L'astuce est la première à utiliser
SELECT SomeString AS [*] FOR XML PATH('')
pour échapper correctement à tous les caractères interdits. C'est la raison pour laquelle je remplace le délimiteur par une valeur magique pour éviter les problèmes avec;
comme délimiteur.Le résultat
la source
J'ai dû écrire quelque chose comme ça récemment. Voici la solution que j'ai trouvée. Il est généralisé pour toute chaîne de délimiteur et je pense que cela fonctionnerait légèrement mieux:
la source
Une solution utilisant un CTE, si quelqu'un en avait besoin (à part moi, qui l'a évidemment fait, c'est pourquoi je l'ai écrit).
la source
Ceci est plus étroitement adapté. Lorsque je fais cela, j'ai généralement une liste d'ID uniques séparés par des virgules (INT ou BIGINT), que je souhaite convertir en table à utiliser comme jointure interne vers une autre table qui a une clé primaire INT ou BIGINT. Je veux qu'une fonction table en ligne soit renvoyée afin d'avoir la jointure la plus efficace possible.
Un exemple d'utilisation serait:
J'ai volé l'idée de http://sqlrecords.blogspot.com/2012/11/converting-delimited-list-to-table.html , en la changeant pour qu'elle soit en ligne avec une valeur de table et convertie en INT.
la source
Il existe une version correcte ici, mais j'ai pensé que ce serait bien d'ajouter un peu de tolérance aux pannes au cas où ils auraient une virgule à la fin ainsi que de la faire pour que vous puissiez l'utiliser non pas comme une fonction mais dans le cadre d'un plus grand morceau de code . Juste au cas où vous ne l'utilisez qu'une seule fois et n'avez pas besoin d'une fonction. C'est également pour les nombres entiers (ce dont j'avais besoin), vous devrez donc peut-être changer vos types de données.
la source
SET @StringToSeperate = @StringToSeperate+','
immédiatement avant laWHILE
boucle, je pense que vous pourriez être en mesure d'éliminer le bloc "ajouter la dernière valeur". Voir aussi mon sol'n sur githubJ'ai modifié un peu la fonction d'Andy Robinson. Maintenant, vous pouvez sélectionner uniquement la partie requise de la table de retour:
SELECT Name FROM dbo.splitstring('ELIS.YD.CRP1.1.CBA.MDSP.T389.BT') WHERE numOrder=5
la source
Si vous avez besoin d'une solution ad-hoc rapide pour les cas courants avec un code minimum, alors ce double ligne CTE récursif le fera:
Utilisez-le comme une instruction autonome ou ajoutez simplement les CTE ci-dessus à l'une de vos requêtes et vous pourrez rejoindre la table résultante
b
avec d'autres pour une utilisation dans d'autres expressions.modifier (par Shnugo)
Si vous ajoutez un compteur, vous obtiendrez un index de position avec la liste:
Le résultat:
la source
Je prends la route xml en enveloppant les valeurs dans des éléments (M mais tout fonctionne):
la source
voici une version qui peut se dédoubler sur un motif en utilisant patindex, une simple adaptation du post ci-dessus. J'ai eu un cas où je devais diviser une chaîne contenant plusieurs caractères de séparation.
le résultat ressemble à ceci
stringa stringb x y z
la source
Personnellement j'utilise cette fonction:
la source
J'ai développé un double séparateur (prend deux caractères séparés) comme demandé ici . Cela pourrait avoir une certaine valeur dans ce thread car il est le plus référencé pour les requêtes relatives au fractionnement de chaînes.
Usage:
Utilisation possible (obtenir la deuxième valeur de chaque fractionnement):
la source
Voici un exemple que vous pouvez utiliser comme fonction ou également mettre la même logique en procédure. --SELECT * à partir de [dbo] .fn_SplitString;
la source
@vCSV
contient des caractères interdits ... Je viens de poster une réponse pour surmonter ce problème.Une solution récursive basée sur le cte
la source
Ceci est basé sur la réponse d'Andy Robertson, j'avais besoin d'un délimiteur autre que la virgule.
Et pour l'utiliser:
(Testé sur SQL Server 2008 R2)
EDIT: code de test correct
la source
/ *
Cas de test: voir l'URL référencée en tant que "fonctionnalité améliorée" ci-dessus
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,b')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,,')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, ')
SELECT *,LEN(Item+'_')-1 'L' from splitstring('a,, c ')
* /
la source
la source
Vous pouvez utiliser cette fonction:
la source
Avec tout le respect que je dois à @AviG, il s'agit de la version sans bogue de la fonction conçue par lui pour renvoyer tous les jetons dans leur intégralité.
la source
Le moyen le plus simple:
Cela fonctionne même en édition express :).
la source