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;
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