В одном из своих предыдущих постов я уже приводил пример как распарсить строку. Теперь хочу поделиться еще одним способом парсинга строки:
- первые две строчки строка, которую нужно распарсить и наш разделитель соответственно;
- в строчках с 4 по 12 мы с помощью CTE создаем таблицу ToTable c двумя столбцами start и end, в которые записываем "координаты" на основании которых будем вырезать из искомой строки наши значения (в столбце start номер позиции в строке начала значения, а в столбце end номер позиции в строке окончания значения), т.е. для нашей строки 'a,b,c' мы получим следующую таблицу:
- в строчках 13-15 мы на основании таблицы ToTable с помощью функции SUBSTRING (куда мы и будем подставлять необходимые значения начала и конца подстроки с нашими значениями) вырезаем наши значения.
Теперь о самом коде:
DECLARE @string NVARCHAR(10) = 'a,b,c' DECLARE @delimiter NVARCHAR(1) = ','; WITH ToTable([START], [END]) AS ( SELECT 1 AS [START] ,CAST(CHARINDEX(@delimiter, @string) AS INT) AS [END] UNION ALL SELECT CAST([END] + 1 AS INT) ,CAST(CHARINDEX(@delimiter, @string, [END] + 1) AS INT) FROM ToTable WHERE [END] > 0 ) SELECT SUBSTRING(@string, [START], CASE WHEN [END] > 0 THEN [END] - [START] ELSE LEN(@string) END) AS [Words] FROM ToTable
- первые две строчки строка, которую нужно распарсить и наш разделитель соответственно;
- в строчках с 4 по 12 мы с помощью CTE создаем таблицу ToTable c двумя столбцами start и end, в которые записываем "координаты" на основании которых будем вырезать из искомой строки наши значения (в столбце start номер позиции в строке начала значения, а в столбце end номер позиции в строке окончания значения), т.е. для нашей строки 'a,b,c' мы получим следующую таблицу:
- в строчках 13-15 мы на основании таблицы ToTable с помощью функции SUBSTRING (куда мы и будем подставлять необходимые значения начала и конца подстроки с нашими значениями) вырезаем наши значения.
И напоследок:
- обратите внимание что в конце строки после последнего значения отсутствует разделитель, если этого не сделать тогда в результирующем наборе будет дополнительное значение - пустая строка
- этот способ работает немного быстрее чем способ, описанный в предыдущем посте о парсинге строки
Полезные ссылки
- CTE (Common Table Expressions)
- функции для работы со строками
Очень полезный запрос!Спасибо большое за такое разностороннее решение проблемы парсинга. Внесу свои "три копейки": здесь опечатка в имени переменной DECLARE @delimiter, а также в третьей строке необходимо добавить ";" - без нее не работает.
ОтветитьУдалитьСпасибо за комментарий и найденные опечатки :) Подправил пост.
УдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьИз этого можно сделать табличную функцию:
ОтветитьУдалитьSET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fnc_ExplodeString] (@string varchar(MAX), @delimiter varchar(MAX))
RETURNS @RESULT TABLE (Substrings varchar(MAX))
AS
BEGIN
WITH ToTable([START], [END]) AS
(
SELECT
1 AS [START],
CAST(CHARINDEX(@delimiter, @string) AS INT) AS [END]
UNION ALL
SELECT
CAST([END] + LEN(@delimiter) AS INT),
CAST(CHARINDEX(@delimiter, @string, [END] + LEN(@delimiter)) AS INT)
FROM
ToTable
WHERE
[END] > 0
)
INSERT INTO @RESULT
SELECT
SUBSTRING
(
@string,
[START],
CASE
WHEN [END] > 0 THEN [END] - [START]
ELSE LEN(@string)
END
) AS [Words]
FROM
ToTable
OPTION
(MAXRECURSION 0)
RETURN
END
GO