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