2011-04-27 13 views
5

je dois extraire un texte qui est entouré par ***[some text] cordes, comme dans l'exemple suivant:Extrait sous-chaîne de chaîne dans SQL

some text 
some text 
***[some text] 
THIS SHOULD BE EXTRACTED 
***[some text] 
some text 
some text 
some text 
some text 
some text 
***[some text] 
THIS SHOULD BE EXTRACTED TOO 
***[some text] 
some text 

la sortie doit être:

THIS SHOULD BE EXTRACTED 
THIS SHOULD BE EXTRACTED TOO 

J'ai essayé PATINDEX comme ici, mais ne trouve pas le moyen d'extraire la corde.

PATINDEX('%[*][*][*][[]%]%%[*][*][*][[]%]%',@Text) 

Je suis impatient d'entendre des suggestions.

+3

Est-ce que le texte que vous présentez représentent un champ, une ligne ou une ligne du jeu? –

+0

@Cos Callis Il représente un champ 'NVARCHAR' – Func

+0

Vous avez un CR LF à la fin de ces lignes? – DKnight

Répondre

2

Pas une solution regex et je suis encore novice SQL afin peut ne pas être optimale, mais vous devriez être en mesure d'analyser avec une boucle WHILE utilisant

CHARINDEX pour le *** puis en utilisant comme point de départ pour
CHARINDEX à la LF utiliser comme point de départ pour une
SUBSTRING avec le point final étant une CHARINDEX de la prochaine ***
concaténer la sous-chaîne à votre sortie, passer devant la désinence *** et boucle pour trouver le suivant.

Je vais jouer avec ça et voir si je peux ajouter un exemple.
EDIT - Cela doit probablement plus de contrôle d'erreur

declare @inText nvarchar(2000) = 'some text 
some text 
***[some text] 
THIS SHOULD BE EXTRACTED 
***[some text] 
some text 
some text 
some text 
some text 
some text 
***[some text] 
THIS SHOULD BE EXTRACTED TOO 
***[some text] 
some text ' 

declare @delim1 nvarchar(50) = '***' 
declare @delim2 char = char(10) 
declare @output nvarchar(1000) = '' 
declare @position int 
declare @positionEnd int 

set @position = CHARINDEX(@delim1,@inText) 
while (@position != 0 and @position is not null) 
BEGIN 
    set @position = CHARINDEX(@delim2,@inText,@position) 
    set @positionEnd = CHARINDEX(@delim1,@inText,@position) 
    set @output = @output + SUBSTRING(@inText,@position,@[email protected]) 
    set @position = CHARINDEX(@delim1,@inText,@positionEnd+LEN(@delim1)) 
END 
select @output 
+1

Je pense que vous pourriez [probablement utiliser ceci comme base] (http://sqlblog.com/blogs/adam_machanic/archive/2006/07/12/pattern-based-split-string.aspx) puis appeler l'UDF en utilisant ' CROSS APPLY' –

+0

@Martin - oooo plus de matériel de lecture - merci pour les commentaires, il est très apprécié – DKnight

+0

+1 Merci pour votre temps, il semble très intéressant. – Func

1

Je peux me tromper, mais je ne pense pas qu'il existe une manière propre de le faire directement dans SQL. Je voudrais utiliser un CLR stored procedure et utiliser des expressions régulières de C# ou votre langage .NET de choix.

Voir this article pour un exemple pertinent utilisant des regexes.

+0

Malheureusement je ne peux pas utiliser les procédures stockées C# ou CLR, je peux effectuer seulement sélectionner des déclarations ... – Func

4

Pour le cas un peu plus facile soulevée dans les commentaires que vous pourriez faire

;WITH T(C) AS 
(
SELECT ' 
    some text 
    some text 
    ***[some text 1] 
    THIS SHOULD BE EXTRACTED 
    ***[some text 2] 
    some text 
    some text 
    some text 
    some text 
    some text 
    ***[some text 1] 
    THIS SHOULD BE EXTRACTED TOO 
    ***[some text 2] 
    some text' 
) 
SELECT col.value('.','varchar(max)') 
FROM T 
CROSS APPLY (SELECT CAST('<a keep="false">' + 
         REPLACE(
          REPLACE(C,'***[some text 2]','</a><a keep="false">'), 
         '***[some text 1]','</a><a keep="true">') + 
        '</a>' AS xml) as xcol) x 
CROSS APPLY xcol.nodes('/a[@keep="true"]') tab(col) 
+0

+1 Merci pour votre temps, je vais examiner cette solution. – Func

+0

J'ai testé votre solution vs mon qui est ci-dessus. Il prend 98% du lot. Mon seulement 2%. Je pense que c'est à cause de XML. – Dalex

+0

Oui, les fonctions du lecteur 'XML' n'ont certainement pas de grandes performances. De plus, ma réponse aurait besoin de plus d'opérations 'REPLACE' si le texte pouvait contenir des caractères tels que' <'afin de les remplacer par les entités XML correspondantes. –

1

Vous pouvez trouver dans mon blog: http://sql-tricks.blogspot.com/2011/04/extract-strings-with-delimiters.html Il est solution pure sans modification supplémentaire, que délimiteurs séquences devraient être decalred.

+0

Merci votre solution est gentille mais j'obtiens le 'paramètre de longueur Invalid passé à la fonction SUBSTRING' quand j'essaye de changer des délimiteurs pour répondre à mes besoins. Aussi c'est un peu lent ou mon serveur est lent, je ne suis pas sûr. – Func

+0

Veuillez écrire vos délimiteurs. Je le réparerai. – Dalex