Функция dbo.fn_split обрезает следующий символ после разделительного символа / разделителя - PullRequest
0 голосов
/ 10 апреля 2019

Я запустил этот запрос:

select * From dbo.fn_split('Age,15,14,193,188 ',',')

Возвращает значения, но обрезает один символ перед каждым значением

Я пытался добавить пробел после каждой запятой, как

select * From dbo.fn_split('Age, 15, 14, 193, 188 ',',')

И это сработало. Но я хочу знать, почему не работает с запятыми

select * From dbo.fn_split ('Age,15,14,193,188 ',',')

Ответы [ 3 ]

2 голосов
/ 10 апреля 2019

Вы не публикуете код fn_split, в котором и заключается проблема. Но если длина ваших строк меньше 8000 символов, эта функция поможет вам оптимально разделить их. Эта функция представляет собой модифицированную версию сплиттера Джеффа Модена производства Eirikur Eirikson.

CREATE FUNCTION [dbo].[DelimitedSplit8K_LEAD]
--===== Define I/O parameters
        (@pString VARCHAR(8000), @pDelimiter CHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
--===== "Inline" CTE Driven "Tally Table” produces values from 0 up to 10,000...
     -- enough to cover VARCHAR(8000)
 WITH E1(N) AS (
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
                 SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
                ),                          --10E+1 or 10 rows
       E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
       E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
 cteTally(N) AS (--==== This provides the "zero base" and limits the number of rows right up front
                     -- for both a performance gain and prevention of accidental "overruns"
                 SELECT 0 UNION ALL
                 SELECT TOP (DATALENGTH(ISNULL(@pString,1))) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
                ),
cteStart(N1) AS (--==== This returns N+1 (starting position of each "element" just once for each delimiter)
                 SELECT t.N+1
                   FROM cteTally t
                  WHERE (SUBSTRING(@pString,t.N,1) = @pDelimiter OR t.N = 0) 
                )
--===== Do the actual split. The ISNULL/NULLIF combo handles the length for the final element when no delimiter is found.
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY s.N1),
        Item = SUBSTRING(@pString,s.N1,ISNULL(NULLIF((LEAD(s.N1,1,1) OVER (ORDER BY s.N1) - 1),0)-s.N1,8000))
   FROM cteStart s
;
GO
0 голосов
/ 15 апреля 2019

ALTER FUNCTION [dbo]. [Fn_Split] (@ text varchar (8000), @delimiter varchar (20) = ',')

ВОЗВРАЩАЕТСЯ ТАБЛИЦА @Strings

(

Позиция в ИДЕНТИЧНОМ ПЕРВИЧНОМ КЛЮЧЕ,

значение varchar (8000)

)

AS

НАЧАТЬ

ОБЪЯВИТЬ @index int

SET @index = -1

WHILE (LEN (@text)> 0)

НАЧАТЬ

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

0 голосов
/ 10 апреля 2019

Я понял, что я делаю не так. В основном я добавил дополнительный пробел в конце строки, которую я хочу разделить. Если вы измените

Select * From dbo.fn_split(dbo.fn_split('Age,15,14,193,188 ',',')) до Select * From dbo.fn_split('Age,15,14,193,188',','). Другими словами, избавившись от лишнего пробела, после числа 188 вы получите желаемый результат.

Решение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...