2016-09-08 1 views
0

Ich habe eine Tabelle mit nur einer Spalte. Diese eine Spalte enthält Zeichenfolgen mit durch Kommas getrennten Werten. Ich versuche, jeden String aus der Tabelle auszuwählen> spalte den String durch Kommas> und füge dann die Ergebnisse in eine andere Tabelle ein.Split-Spalte Wert mit Trennzeichen und Einfügen in verschiedene Tabelle

Meine erste Tabelle sieht wie folgt aus:

DataString 
abc,def,gh,i,jkl 
mnop,qr,stu,v,wxyz 

Ich würde die Daten gerne wie folgt aussehen:

Value1 Value2 Value3 Value4 Value5 
abc  def  gh  i  jkl 
mnop  qr  stu  v  wxyz 

Dies ist der Code, den ich habe bisher:

DECLARE @valueList varchar(100) 
DECLARE @pos INT 
DECLARE @len INT 
DECLARE @value varchar(100) 
Select @valueList = DataString from [dbo].[rawdata] 


set @pos = 0 
set @len = 0 

WHILE CHARINDEX(',', @valueList, @pos+1)>0 
BEGIN 
    set @len = CHARINDEX(',', @valueList, @pos+1) - @pos 
    set @value = SUBSTRING(@valueList, @pos, @len) 

    insert into [dbo].[tempTable] (Value1) Values (@value)  

    set @pos = CHARINDEX(',', @valueList, @[email protected]) +1 
END 

Ich habe zwei Probleme mit diesem Code.

Problem 1: - meine Select-Anweisung, um die Spalte DataString in die Variable @ valueList ziehen zieht nur die letzte Zeile in der Tabelle, anstatt alle auszuwählen.

Problem 2: - meine Insert-Anweisung kann nur die Werte als neue Zeilen in die Tabelle einfügen. Ich kann nicht herausfinden, wie man die Werte in ihre entsprechenden Spalten einträgt.

Jede Hilfe, wie Sie eines meiner Probleme beheben, wäre sehr willkommen.

+0

benötigt Sie wahrscheinlich für jede Zeile eine Art eindeutiger Kennung benötigen (zB jeden zuweisen Zeile eine Zeilennummer), dann teilen Sie jede Zeile mit einem Standard s plit-Funktion (oder verwenden Sie Ihre eigenen) und drehen Sie die Ergebnisse. – ZLK

Antwort

0

Ihr erstes Problem ist, dass das Zuweisen einer Variablen zu einer Spalte wie der in einer Tabelle nur eine Zeile aus dieser Spalte in der Tabelle zieht. Wenn Sie jede Zeile in einer Spalte durchlaufen möchten, wie Sie es gerade tun, müssen Sie eine CURSOR oder eine Variante wie diese verwenden, um durch jede Zeile zu gehen.

Das zweite Problem, das Sie haben, ist, dass Ihre while-Anweisung falsch ist. Sie verpassen den letzten Wert, weil Sie aufhören, wenn in Ihrem Datastring keine Kommas mehr stehen. Beim letzten Wert sind keine Kommas mehr vorhanden, daher wird der letzte Wert übersprungen. Es gibt einen Weg, um dies mit Ihrer aktuellen Methode zu umgehen, aber ich würde eine alternative Methode zur Aufteilung Ihrer Zeichenfolge empfehlen.

DECLARE @myTable TABLE (datastring VARCHAR(4000)); 
INSERT @myTable(datastring) 
VALUES ('abc,def,gh,i,jkl'),('mnop,qr,stu,v,wxyz'); 

DECLARE @valueList VARCHAR(4000) = '', @i INT = 1, @pos INT = 0, @len INT = 0, @value VARCHAR(100) = ''; 
IF OBJECT_ID('tempTable', 'U') IS NOT NULL DROP TABLE tempTable; 
CREATE TABLE tempTable (OriginalDataString VARCHAR(4000), stringVal VARCHAR(255), valNum INT); 

DECLARE curs CURSOR FOR 
SELECT datastring 
FROM @myTable; 

OPEN curs; 
FETCH NEXT FROM curs INTO @valueList; 
WHILE @@FETCH_STATUS = 0 BEGIN 
    SELECT @pos = 0, @len = 0, @i = 1; 
    WHILE 1 = 1 
    BEGIN 
     SET @len = ISNULL(NULLIF(CHARINDEX(',', @valueList, @pos+1), 0) - @pos, LEN(@valueList)); 
     SET @value = SUBSTRING(@valueList, @pos, @len); 

     INSERT tempTable(OriginalDataString, stringVal, valNum) 
     VALUES (@valueList, @value, @i); 

     IF CHARINDEX(',', @valueList, @pos+1) = 0 
      BREAK; 

     SET @pos = CHARINDEX(',', @valueList, @[email protected]) + 1; 
     SET @i += 1; 
    END 
    FETCH NEXT FROM curs INTO @valueList; 
END 
CLOSE curs; 
DEALLOCATE curs; 

SELECT MAX(CASE WHEN valNum = 1 THEN stringVal END) val1 
    , MAX(CASE WHEN valNum = 2 THEN stringVal END) val2 
    , MAX(CASE WHEN valNum = 3 THEN stringVal END) val3 
    , MAX(CASE WHEN valNum = 4 THEN stringVal END) val4 
    , MAX(CASE WHEN valNum = 5 THEN stringVal END) val5 
FROM tempTable 
GROUP BY OriginalDataString; 

Dieser verwendet einen Cursor jedes Datenstring in Ihrem Tisch zu bekommen, setzt jeden Wert in einem Cursor, so dass sie eine Schleife durch den Wert zu erhalten (die Schleife bricht, wenn Sie das Ende der Schnur zu erreichen) und wählen dann val1 , val2, val3, val4, val5 aus der resultierenden Tabelle.

Aber, anstatt einen Cursor und eine while-Schleife zu verwenden, würde ich die viel einfachere Verwendung eines rekursiven CTE (oder noch besser, eine Split-Funktion, die Sie bereits eingebaut haben).

Zum Beispiel

DECLARE @myTable TABLE (datastring VARCHAR(4000)); 
INSERT @myTable(datastring) 
VALUES ('abc,def,gh,i,jkl'),('mnop,qr,stu,v,wxyz'); 

WITH CTE AS (
    SELECT datastring 
     , SUBSTRING(datastring, 1, ISNULL(NULLIF(CHARINDEX(',', datastring), 0) - 1, LEN(datastring))) sString 
     , NULLIF(CHARINDEX(',', datastring), 0) cIndex 
     , 1 Lvl 
    FROM @myTable T 
    UNION ALL 
    SELECT datastring 
     , SUBSTRING(datastring, cIndex + 1, ISNULL(NULLIF(CHARINDEX(',', datastring, cIndex + 1), 0) - 1 - cIndex, LEN(datastring))) 
     , NULLIF(CHARINDEX(',', datastring, cIndex + 1), 0) 
     , Lvl + 1 
    FROM CTE 
    WHERE cIndex IS NOT NULL) 
SELECT MAX(CASE WHEN Lvl = 1 THEN sString END) val1 
    , MAX(CASE WHEN Lvl = 2 THEN sString END) val2 
    , MAX(CASE WHEN Lvl = 3 THEN sString END) val3 
    , MAX(CASE WHEN Lvl = 4 THEN sString END) val4 
    , MAX(CASE WHEN Lvl = 5 THEN sString END) val5 
    --, datastring OriginalDataString 
FROM CTE 
GROUP BY datastring; 
+0

Das hat so viel geholfen! Vielen Dank! –

0
Declare @YourTable table (DataString varchar(250)) 
Insert Into @YourTable values 
('abc,def,gh,i,jkl'), 
('mnop,qr,stu,v,wxyz') 

Select A.* 
     ,Value1=B.Pos1 
     ,Value2=B.Pos2 
     ,Value3=B.Pos3 
     ,Value4=B.Pos4 
     ,Value5=B.Pos5 
From @YourTable A 
Cross Apply (Select * from [dbo].[udf-Str-Parse-Row](A.DataString,',')) B 

Returns

DataString   Value1 Value2 Value3 Value4 Value5 
abc,def,gh,i,jkl abc  def  gh  i  jkl 
mnop,qr,stu,v,wxyz mnop qr  stu  v  wxyz 

Dann, wenn UDF

CREATE FUNCTION [dbo].[udf-Str-Parse-Row] (@String varchar(max),@Delimeter varchar(10)) 
--Usage: Select * from [dbo].[udf-Str-Parse-Row]('Dog,Cat,House,Car',',') 
--  Select * from [dbo].[udf-Str-Parse-Row]('John Cappelletti',' ') 
--  Select * from [dbo].[udf-Str-Parse-Row]('id26,id46|id658,id967','|') 

Returns Table 

As 

Return (
    SELECT Pos1 = xDim.value('/x[1]','varchar(250)') 
      ,Pos2 = xDim.value('/x[2]','varchar(250)') 
      ,Pos3 = xDim.value('/x[3]','varchar(250)') 
      ,Pos4 = xDim.value('/x[4]','varchar(250)') 
      ,Pos5 = xDim.value('/x[5]','varchar(250)') 
      ,Pos6 = xDim.value('/x[6]','varchar(250)') 
      ,Pos7 = xDim.value('/x[7]','varchar(250)') 
      ,Pos8 = xDim.value('/x[8]','varchar(250)') 
      ,Pos9 = xDim.value('/x[9]','varchar(250)') 
    FROM (Select Cast('<x>' + Replace(@String,@Delimeter,'</x><x>')+'</x>' as XML) as xDim) A 
) 
Verwandte Themen