2017-08-14 33 views
5

Mam wartość ciągu znaków, która ma wartości numeryczne oddzielone przecinkiem, a następnie potoku. Chcę podzielić je na tabelę z dwiema kolumnami. Mogłem podzielić ciąg znaków jednym ogranicznikiem, ale niestety nie mogłem znaleźć sposobu na podzielenie go przez dwa. Proszę pomóż.Podziel ciąg przez dwa ograniczniki na dwie kolumny

DECLARE @list NVARCHAR(MAX) = '1,101|2,202|3,303'; 

Wynik powinien być jak poniżej.

1 101 
2 202 
3 303 

Z góry dziękuję.

+0

Czytałaś ten [post] (https://stackoverflow.com/a/28109664/1050927) jeszcze? – Prisoner

+0

czy będą tylko dwie kolumny?, Mam na myśli '1.101' – TheGameiswar

Odpowiedz

1

Jeśli używasz SQL Server 2016 lub Azure, masz dostęp do nowej SPLIT_STRING funkcji. Jeśli nie polecam korzystania z funkcji Jeff AFN za DelimitedSplit8K, który jest powszechnie uważany za najszybszy i najbardziej efektywny SQL oparte rozdzielacz strun dostępnych ...

DECLARE @list NVARCHAR(MAX) = '1,101|2,202|3,303'; 

SELECT 
    Col1 = LEFT(dsk.Item, sl.SplitLocation - 1), 
    Col2 = SUBSTRING(dsk.Item, sl.SplitLocation + 1, LEN(dsk.Item)) 
FROM 
    dbo.DelimitedSplit8K(@list, '|') dsk -- code for DelimitedSplit8K can be found here... http://www.sqlservercentral.com/articles/Tally+Table/72993/ 
    CROSS APPLY (VALUES (ISNULL(NULLIF(CHARINDEX(',', dsk.Item, 1), 0), 1))) sl (SplitLocation); 
0
CREATE FUNCTION [dbo].[fn_Split_char](@text nvarchar(max), @delimiter varchar(20) = ' ') 
RETURNS @Strings TABLE 
( 
    position int IDENTITY PRIMARY KEY, 
    value nvarchar(max) 
) 
AS 
BEGIN 

DECLARE @index int 
SET @index = -1 

WHILE (LEN(@text) > 0) 
    BEGIN 
    SET @index = CHARINDEX(@delimiter , @text) 
    IF (@index = 0) AND (LEN(@text) > 0) 
     BEGIN 
     INSERT INTO @Strings VALUES (@text) 
      BREAK 
     END 
    IF (@index > 1) 
     BEGIN 
     INSERT INTO @Strings VALUES (LEFT(@text, @index - 1)) 
     SET @text = RIGHT(@text, (LEN(@text) - @index)) 
     END 
    ELSE 
     SET @text = RIGHT(@text, (LEN(@text) - @index)) 
    END 
    RETURN 
END 



Select LEFT(value, Charindex(',', value) - 1) , 
RIGHT(value, Charindex(',', Reverse(value)) - 1) , 
* from [fn_Split_char] ('1,101|2,202|3,303', '|') 
+0

Używanie pętli WHILE do analizy łańcuchów jest niezwykle nieefektywne i nigdy nie powinno być wykonywane. Istnieją inne metody, które są o kilka rzędów wielkości lepsze. –

0

stosować xml ścieżkę i zastosować krzyż tworzenie wielu wierszy dla pojedynczego wiersza w oparciu na separatorze rury, a następnie użyć podciąg WRT przecinki w celu uzyskania pożądanych dwie kolumny

Create table #temp(list nvarchar(max)) 
Insert into #temp values('1,101|2,202|3,303') 
SELECT 
    Substring(Tbl.Col.value('./text()[1]','varchar(50)'),1,1)as col1, 
    Substring(Tbl.Col.value('./text()[1]','varchar(50)'),charindex(',',Tbl.Col.value('./text()[1]','varchar(50)'),1)+1,len(Tbl.Col.value('./text()[1]','varchar(50)'))) 
FROM 
(Select cast('<a>'+ replace((SELECT list As [*] FOR XML PATH ('')), '|', '</a><a>') + '</a>' as xml)as t 
    from #temp) tl 
Cross apply 
tl.t.nodes('/a') AS Tbl(Col) 
0

Spróbuj użyć tej funkcji wycenione tabela, zamieścić na swojej głównej SP SP

ALTER FUNCTION [dbo].[delimiter] 
(
@PARAM_IDS AS VARCHAR(MAX) 
@PARAM_DELIMITER AS CHAR(1) 
) 
RETURNS 
@NEW_TABLE TABLE 
(
NUM INT NOT NULL IDENTITY, 
ID INT NOT NULL 
) 
AS 
BEGIN 
DECLARE @NEXTSTRING AS NVARCHAR(MAX); 
DECLARE @POS AS INT; 
DECLARE @STRING AS NVARCHAR(MAX); 
DECLARE @DELIMITER AS NVARCHAR(MAX); 
SET @STRING = @PARAM_IDS; 
SET @DELIMITER = @PARAM_DELIMITER; 
SET @STRING = @STRING + @DELIMITER; 
SET @POS = CHARINDEX(@DELIMITER,@STRING); 

WHILE (@POS <> 0) 
BEGIN 
    SET @NEXTSTRING = SUBSTRING(@STRING,1,@POS - 1); 
    INSERT @NEW_TABLE (ID) VALUES (@NEXTSTRING); 
    SET @STRING = SUBSTRING(@STRING,@POS+1,len(@STRING)); 
    SET @POS = CHARINDEX(@DELIMITER,@STRING); 
END 
    RETURN 
END 

następnie przykładem wykorzystania

SET @DETAILS_COUNT = (SELECT COUNT(*) FROM delimiter(@PARAM_MS_UNIT_ID, @DELIMITER));