2017-08-14 63 views
5

Virgülle ve sonra bir boruyla ayrılmış sayısal değerler içeren bir dize değeri var. Onları iki sütunlu bir masaya bölmek istiyorum. Dizgiyi bir sınırlayıcıyla bölebilirdim ama maalesef ikiye bölme yolu bulamadı. Lütfen yardım et.İki sınırlayıcıyla dize iki sütun halinde bölünmüş

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

Sonuç, aşağıdaki gibi olmalıdır.

1 101 
2 202 
3 303 

Şimdiden teşekkürler. SQL Server 2016 veya Azure kullanıyorsanız

+0

bu [yazı] okudunuz (https://stackoverflow.com/a/28109664/1050927) henüz? – Prisoner

+0

sadece iki sütun olacak mıdır, yani 1.101' – TheGameiswar

cevap

1

, yeni SPLIT_STRING işlevine erişim hakkına sahiptir. Jeff Moden en yaygın olarak kullanılan en hızlı, en verimli SQL tabanlı dize splitter olarak kabul edilir DelimitedSplit8K işlevini ...

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

Dizeleri ayrıştırmak için bir WHILE döngüsünü kullanmak son derece verimsiz ve asla yapılmamalıdır. Büyüklük dereceleri daha iyi olan başka yöntemler vardır. –

0

Kullanım xml yolunu kullanmanızı öneriyoruz ve çapraz geçerli değilse dayalı tek satır için birden çok satır oluşturmak için boru ayırıcı ve daha sonra iki istenilen sütunları

türetmek için wrt virgül alt dize kullanmak
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

, bu tablo değerli İşlevini kullanmayı deneyin ana SP bu SP gömmek

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 

sonra kullanım örneği

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