2011-05-11 3 views
0

J'utilise SQL Ser 2008 et j'ai une grande table avec une seule colonne de données. Les données sont une chaîne aléatoire avec très peu de cohérence. Exemple: Nom de compte 445566 0010020056893010445478008 AFD 369. J'ai travaillé avec une fonction split proposée par un utilisateur de stackoverflow. Cela fonctionne très bien mais la fonction assigne la chaîne divisée en une colonne. J'ai besoin d'une rangée de colonnes individuelles. Le résultat actuel est 1col avec les valeurs Name, Account, 445566, ... mais le résultat que je recherche est col1 Name, col2 Account, col3 445566, ... Si quelqu'un pouvait donner un aperçu sur la façon d'adapter ce script ou son utilisation pour obtenir le résultat souhaité, il serait très apprécié.SQL Server 2008 T-SQL UDF Split() Tailoring

CREATE FUNCTION [dbo].[Split] 
( 
@String varchar(max) 
,@Delimiter char 
) 
RETURNS @Results table 
( 
Ordinal int 
,StringValue varchar(max) 
) 
as 
begin 

set @String = isnull(@String,'') 
set @Delimiter = isnull(@Delimiter,'') 

declare 
@TempString varchar(max) = @String 
,@Ordinal int = 0 
,@CharIndex int = 0 

set @CharIndex = charindex(@Delimiter, @TempString) 
while @CharIndex != 0 begin  
    set @Ordinal += 1   
    insert @Results values 
    ( 
    @Ordinal 
    ,substring(@TempString, 0, @CharIndex) 
    )   
    set @TempString = substring(@TempString, @CharIndex + 1, len(@TempString) - @CharIndex)  
    set @CharIndex = charindex(@Delimiter, @TempString) 
end 

if @TempString != '' begin 
    set @Ordinal += 1 
    insert @Results values 
    ( 
    @Ordinal 
    ,@TempString 
    ) 
end 

return 
end 

--The usage: 
SELECT  
* 
FROM  
mytable M  
CROSS APPLY  
[dbo].[Split] (M.TheColumn, ' ') S 
Where rtrim(s.StringValue) != '' 
+0

Soit dit en passant, la fonction est empruntée à @antisanity et son utilisation sur la table venait de @gbn. Merci les gars! – 2boolORNOT2bool

+0

Qu'essayez-vous d'accomplir? Ces données sont-elles conservées ou s'agit-il d'une importation? La largeur de la table de sortie variera-t-elle ou sera-t-elle statique? – canon

+0

Je suis l'ingénierie inverse d'un ancien lot de fichiers à plat. Les données sont constituées de chaînes contenant 120 caractères. La largeur de la table sera un nombre statique de colonnes. Mon but est de décomposer la chaîne en une rangée de colonnes et pas seulement une colonne contenant toutes les données mais 9 ou 10 colonnes. Cela affectera quelque chose comme 10000 lignes de données à la fois. Merci encore l'antisanité pour toute aide! – 2boolORNOT2bool

Répondre

1

Si vous savez que vous avez 6 colonnes dans la chaîne, vous pouvez utiliser une fonction split qui ressemble à ceci et bien sûr la fonction modifient à tout ce que le nombre de colonnes que vous voulez. Une fonction ne peut pas renvoyer un nombre dynamique de colonnes.

create function dbo.Split6(@String varchar(max), @Delimiter char(1)) 
returns table as return 
(
    select 
    substring(T.Col, 1, S1.Pos-1) as Col1, 
    substring(T.Col, S1.Pos+1, S2.Pos-S1.Pos-1) as Col2, 
    substring(T.Col, S2.Pos+1, S3.Pos-S2.Pos-1) as Col3, 
    substring(T.Col, S3.Pos+1, S4.Pos-S3.Pos-1) as Col4, 
    substring(T.Col, S4.Pos+1, S5.Pos-S4.Pos-1) as Col5, 
    substring(T.Col, S5.Pos+1, S6.Pos-S5.Pos-1) as Col6 
    from (select @String+replicate(@Delimiter, 6)) as T(Col) 
    cross apply (select charindex(@Delimiter, T.Col, 1)) as S1(Pos) 
    cross apply (select charindex(@Delimiter, T.Col, S1.Pos+1)) as S2(Pos) 
    cross apply (select charindex(@Delimiter, T.Col, S2.Pos+1)) as S3(Pos) 
    cross apply (select charindex(@Delimiter, T.Col, S3.Pos+1)) as S4(Pos) 
    cross apply (select charindex(@Delimiter, T.Col, S4.Pos+1)) as S5(Pos) 
    cross apply (select charindex(@Delimiter, T.Col, S5.Pos+1)) as S6(Pos) 
) 

Test:

declare @T table (Col varchar(100)) 

insert into @T values 
('Name Account 445566 0010020056893010445478008 AFD 369'), 
(''), 
('1 2'), 
('1 3') 

select S.Col1, S.Col2, S.Col3, S.Col4, S.Col5, S.Col6 
from @T as T 
    cross apply 
    dbo.Split6(T.Col, ' ') as S 

Résultat:

Col1 Col2  Col3 Col4      Col5 Col6 
---- ------- ------ ------------------------- ---- ---- 
Name Account 445566 0010020056893010445478008 AFD 369 

1  2    
1    3    
+0

Cela semble bon. Je finirai par trouver exactement combien de colonnes j'ai besoin donc je pense que cela fonctionnera bien! Merci! – 2boolORNOT2bool

0

Vous pourriez essayer d'utiliser un PIVOT.

http://msdn.microsoft.com/en-us/library/ms177410.aspx

+0

Je devrais pouvoir PIVOTER la colonne de la table après que le script soit utilisé mais je cherchais un moyen de contourner cela. Mes pensées étaient si vous pouvez séparer une chaîne et insérer les données à une colonne peut-être que vous pourriez l'assigner à plusieurs colonnes différentes dans le script. – 2boolORNOT2bool

+0

Je sais que cela ne ressemble pas à l'outil le plus évident, mais je suis à moitié de la performance (pivoter une table avec plus de 100000 lignes, espérons ne pas frapper le CPU deux fois va prendre un certain temps couplé avec le processus fois) et la moitié juste essayer de voir si cela pourrait être fait. Je ne connais pas bien le T-Sql, alors j'ai pensé demander aux experts. – 2boolORNOT2bool