J'ai un nvarchar (200) appelé ColumnA dans Table1 qui contient, par exemple, la valeur:
ABCDEFG BCDEFGH CDEFGHI DEFGHIJ EFGHIJK FGHIJKL GHIJKLM HIJKLMN IJKLMNO JKLMNOP KLMNOPQ LMNOPQR MNOPQRS NOPQRST OPQRSTU PQRSTUV QRSTUVW RSTUVWX STUVWXY TUVWXYZ
Je veux extraire tous les 7 caractères dans Table2, ColumnB et finir avec tous de ces valeurs ci-dessous.
ABCDEFGHIJKLMNOPQRSTUVWXYZ
[Pas les vrais noms de table et de colonne.]
Les données sont en cours de chargement dans Table1 et Table2 dans un package SSIS, et je me demande s'il est préférable de gérer la chaîne dans TSQL dans une tâche SQL ou d'analyser la chaîne dans un composant de script VB.
[Oui, je pense que nous sommes les quatre derniers de la planète à utiliser VB dans les composants de script. Je ne peux pas convaincre les trois autres que ce truc C # est là pour rester. Cependant, c'est peut-être le moment idéal pour devenir voyou.]
4 Réponses :
Vous pouvez le faire avec T-SQL comme ceci:
DECLARE C CURSOR LOCAL FOR SELECT [ColumnA] FROM [Table1] OPEN C DECLARE @Val nvarchar(200); FETCH NEXT FROM C into @Val WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @I INTEGER; SELECT @I = 1; WHILE @I <= LEN(@vAL)-6 BEGIN PRINT SUBSTRING(@Val, @I, 7) SELECT @I = @I + 1 END FETCH NEXT FROM C into @Val END CLOSE C
CURSOR
a été introduit par le diable de la pensée procédurale pour nous conduire les pauvres petits utilisateurs de bases de données dans le noir et le mal. Entrez dans la lumière de la réflexion basée sur les ensembles et évitez les fonctions CURSOR
, WHILE
et multi-instructions à chaque fois tu peux. :-)
Vous pouvez utiliser un CTE récursif calculant les décalages pas à pas et substring()
.
WITH cte AS ( SELECT 1 n UNION ALL SELECT n + 1 n FROM cte WHERE n + 1 <= len('ABCDEFGHIJKLMNOPQRSTUVWXYZ') - 7 + 1 ) SELECT substring('ABCDEFGHIJKLMNOPQRSTUVWXYZ', n, 7) FROM cte;
J'aime cette approche, mais chaque fois que vous utilisez un CTE récursif pour créer un tally-on-the-fly , vous devez être conscient de la profondeur maximale de 100 qui peut nécessiter une OPTION MAXRECURSION < / code> sur la requête la plus externe chaque fois que vous utilisez ceci ... C'est pourquoi je recherche une table de nombres ou une solution via
ROW_NUMBER
par rapport à un ensemble plus grand (que vous pouvez CROISER) à n'importe quel nombre nécessaire. J'ai placé une réponse moi-même .... +1 de mon côté.
Si vous avez une table de nombres physiques, c'est facile. Sinon, vous pouvez créer un tally-on-the-fly :
WITH Tally(Nmbr) AS (SELECT TOP(LEN(@string)-6) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values) SELECT Nmbr ,SUBSTRING(@string,Nmbr,7) AS FragmentOf7 FROM Tally ORDER BY Nmbr;
- Nous créons le pointage en utilisant ROW_NUMBER
contre tout table avec suffisamment de lignes.
DECLARE @string VARCHAR(100)='ABCDEFGHIJKLMNOPQRSTUVWXYZ';
L'idée en bref:
Le décompte renvoie une liste de nombres de 1 à n (n = LEN (@string) -6). Ce numéro est utilisé dans SUBSTRING
pour définir la position de départ.
En supposant que le nom de la colonne d'entrée est Column1
Synchronous Input
sur Aucun
outColumn1
) Dim idx as integer = 0 While Row.Column1.length > idx + 7 Output0Buffer.AddRow() Output0Buffer.outColumn1 = Row. Column1.Substring(idx,7) idx +=1 End While