2009-06-04 11 views
6

Meine Google-Suchen auf, wie eine Zeichenfolge auf einem Trennzeichen aufgeteilt hat in einigen nützlichen Funktionen für das Aufspalten Strings ergibt, wenn die Zeichenfolge bekannt sind (dh siehe unten):SQL 2005 Split Comma Separated Spalte auf Delimiter

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER FUNCTION [dbo].[Split] (@String varchar(8000), @Delimiter char(1))  
    returns @temptable TABLE (items varchar(8000))  
    as  
    begin  
     declare @idx int  
     declare @slice varchar(8000)  

     select @idx = 1  
      if len(@String)<1 or @String is null return  

     while @idx!= 0  
     begin  
      set @idx = charindex(@Delimiter,@String)  
      if @idx!=0  
       set @slice = left(@String,@idx - 1)  
      else  
       set @slice = @String  

      if(len(@slice)>0) 
       insert into @temptable(Items) values(@slice)  

      set @String = right(@String,len(@String) - @idx)  
      if len(@String) = 0 break  
     end 
    return  
    end 

das funktioniert gut für einen bekannten String wie:

SELECT TOP 10 * FROM dbo.Split('This,Is,My,List',',') 

Allerdings würde Ich mag eine Spalte an eine Funktion zu übergeben, und haben es mit meinen anderen Daten in einem eigenen Zeile unioned zusammen ... zum Beispiel angesichts der Daten :

CommaColumn ValueColumn1 ValueColumn2 
----------- ------------ ------------- 
ABC,123  1    2 
XYZ, 789  2    3 

Ich möchte so etwas wie schreiben:

SELECT Split(CommaColumn,',') As SplitValue, ValueColumn1, ValueColumn2 FROM MyTable 

Und zurück

SplitValue ValueColumn1 ValueColumn2 
---------- ------------ ------------ 
ABC   1    2 
123   1    2 
XYZ   2    3 
789   2    3 

Ist das möglich erhalten, oder hat, bevor jemand dies getan?

+1

99% der Zeit oder Mehr Kommas getrennte Spalten sind ein Ergebnis schlechter Datenbankdesi gn an erster Stelle. Die einzige Stelle für eine Split-Funktion auf Serverebene ist das Refactoring dieser Spalten in ihre eigene Tabelle. –

+0

Ich hoffe, dass diese Tabelle von Ihnen Staging-Datenbank ist und Rohdaten von einem proprietären System enthält, wo Sie keine Möglichkeit haben, das Tabellenlayout zu ändern? – VVS

Antwort

13

Ja, es ist möglich, mit CROSS APPLY (SQL 2005+):

with testdata (CommaColumn, ValueColumn1, ValueColumn2) as (
    select 'ABC,123', 1, 2 union all 
    select 'XYZ, 789', 2, 3 
) 
select 
    b.items as SplitValue 
, a.ValueColumn1 
, a.ValueColumn2 
from testdata a 
cross apply dbo.Split(a.CommaColumn,',') b 

Hinweise:

  1. Sie sollten einen Index der Ergebnismenge Ihrer geteilten Spalte hinzuzufügen, so dass es gibt zwei Spalten, IndexNumber und Value, zurück.

  2. Inline-Implementierungen mit einer Nummerentabelle sind in der Regel schneller als Ihre prozedurale Version.

zB:

create function [dbo].[Split] (@list nvarchar(max), @delimiter nchar(1) = N',') 
returns table 
as 
return (
    select 
    Number = row_number() over (order by Number) 
    , [Value] = ltrim(rtrim(convert(nvarchar(4000), 
     substring(@list, Number 
     , charindex(@delimiter, @[email protected], Number)-Number 
     ) 
    ))) 
    from dbo.Numbers 
    where Number <= convert(int, len(@list)) 
    and substring(@delimiter + @list, Number, 1) = @delimiter 
) 

Erland Sommarskog hat die endgültige Seite auf das, denke ich: http://www.sommarskog.se/arrays-in-sql-2005.html

+0

Ausgezeichneter Peter.Gespeichert meine a ** aus vielen Schwierigkeiten :) –

10

Korrigieren Sie den richtigen Weg - machen Sie diese Spalte zu einer verwandten Tabelle. Von kommaseparierten Skalarsäulen kommt nie etwas Gutes.

+0

Leider nicht meine ideale Situation, aber immer noch richtig. –

0

Sie könnten versuchen, so etwas wie:

SELECT s.Items AS SplitValue, ValueColumn1, ValueColumn2 
FROM MyTable, Split(CommaColumn,',') AS s 
+0

Das könnte tatsächlich funktionieren .. ich denke. – VVS

+0

Ugh, schlechte Join-Syntax auch. –

+0

Versucht dies, was leider nicht funktioniert .. danke für Ihren Versuch. –

1

+1 auf die anti-CSV Kommentare, aber wenn Sie dies tun, müssen Sie verwenden würden CROSS APPLY oder OUTER APPLY.

1
alter procedure [dbo].[usp_split](@strings varchar(max)) as 
begin 
    Declare @index int 
    set @index=1 
    declare @length int 
    set @length=len(@strings) 
    declare @str varchar(max) 
    declare @diff int 
    declare @Tags table(id varchar(30)) 
    while(@index<@length) 
    begin 
     if(@index='1') 
     begin 
      set @str=(SELECT substring(@strings, @index, (charindex(',',(substring(@strings, @index,(@length)))))-1)) 
      insert into @Tags values(@str) 
       set @index=(charindex(',',(substring(@strings, @index,(@length))))) 
     end 
     else 
     begin 
      set @[email protected]@index 
      if(@diff !=0) 
      begin 
       set @str=(select substring(@strings, @index, (charindex(',',(substring(@strings,@index,@diff))))-1)) 
       if(@str is not null and @str!='') 
       begin 
        insert into @Tags VALUES(@str) 
       end 
       set @[email protected] +(charindex(',',(substring(@strings, @index,@diff)))) 
      end 
     end 
    end 
    set @str=(select right(@strings,(charindex(',',(substring(reverse(@strings),1,(@length)))))-1)) 
    insert into @Tags VALUES(@str) 
    select id from @Tags 
end 

Verbrauch:

exec usp_split '1212,21213,1,3,133,1313131,1,231313,5' 
Verwandte Themen