У меня есть строка в базе данных, разделенная запятой. Подобно "Яблоко, банан, ананас, виноград" Мне нужно разбить эту строку на основе запятой и перебрать ее. Поскольку в sql-сервере нет встроенной функции, существует ли какой-либо эффективный способ достижения этой цели.
Разделение строки на сервере sql
Ответ 1
Попробуйте эту функцию
CREATE FUNCTION [dbo].[func_Split]
(
@DelimitedString varchar(8000),
@Delimiter varchar(100)
)
RETURNS @tblArray TABLE
(
ElementID int IDENTITY(1,1), -- Array index
Element varchar(1000) -- Array element contents
)
AS
BEGIN
-- Local Variable Declarations
-- ---------------------------
DECLARE @Index smallint,
@Start smallint,
@DelSize smallint
SET @DelSize = LEN(@Delimiter)
-- Loop through source string and add elements to destination table array
-- ----------------------------------------------------------------------
WHILE LEN(@DelimitedString) > 0
BEGIN
SET @Index = CHARINDEX(@Delimiter, @DelimitedString)
IF @Index = 0
BEGIN
INSERT INTO
@tblArray
(Element)
VALUES
(LTRIM(RTRIM(@DelimitedString)))
BREAK
END
ELSE
BEGIN
INSERT INTO
@tblArray
(Element)
VALUES
(LTRIM(RTRIM(SUBSTRING(@DelimitedString, 1,@Index - 1))))
SET @Start = @Index + @DelSize
SET @DelimitedString = SUBSTRING(@DelimitedString, @Start , LEN(@DelimitedString) - @Start + 1)
END
END
RETURN
END
Пример использования - просто передайте функцию с разделителем с запятой, а также с вашим обязательным разделителем.
DECLARE @SQLStr varchar(100)
SELECT @SQLStr = 'Mickey Mouse, Goofy, Donald Duck, Pluto, Minnie Mouse'
SELECT
*
FROM
dbo.func_split(@SQLStr, ',')
Результат будет таким:
Ответ 2
... Поскольку в sql-сервере нет встроенной функции...
Это было верно в то время, когда вы задавали этот вопрос, но SQL Server 2016 вводит STRING_SPLIT
.
Итак, вы можете просто использовать
SELECT value
FROM STRING_SPLIT ('apple,banana,pineapple,grapes', ',')
Существуют некоторые ограничения (принимаются только одиночные разделители символов и отсутствие какого-либо столбца, указывающего, что индекс разделения является наиболее привлекательным для глаз). Различные ограничения и некоторые обнадеживающие результаты тестирования производительности находятся в в этом блоге Аарона Бертран.
Ответ 3
Вы можете преобразовать свои данные в XML, заменив запятую собственным тегом, в данном случае <w>
для слова.
create table t(col varchar(255));
insert into t values ('apple,banana,pineapple,grapes');
insert into t values ('car,bike,airplane');
select cast(('<w>' + replace(col, ',', '</w><w>') + '</w>') as xml) as xmlValue
from t
Который возвращается
| XMLVALUE |
|--------------------------------------------------------|
| <w>apple</w><w>banana</w><w>pineapple</w><w>grapes</w> |
| <w>car</w><w>bike</w><w>airplane</w> |
Теперь, если вы используете этот запрос в качестве внутреннего выделения XML, внешний запрос может разбить его на отдельные строки:
Решение:
select split.xmlTable.value('.', 'varchar(255)') as xmlValue
from (
select cast(('<w>' + replace(col, ',', '</w><w>') + '</w>') as xml) as xmlValue
from t
) as xmlTable
cross apply xmlValue.nodes ('/w') as split(xmlTable);
Ответ 4
У меня есть решение с помощью рекурсии следующим образом
Create function split_string(@str as nvarchar(max),@separator as char(1)) returns @myvalues Table (id int identity(1,1),myval nvarchar(100))
as
--Kamel Gazzah
--23/04/2019
begin
with cte as(
select @str [mystr],
cast(1 as int) [Start],
charindex(@separator,@str)as Nd
union all
select substring(@str,nd+1,len(@str)),cast(Nd+1 as int),charindex(@separator,@str,Nd+1) from cte
where nd>0
)
insert into @myvalues(myval)
select case when nd>0 then substring(@str,start,Nd-start)
else substring(@str,start,len(@str)) end [splitted]
from cte OPTION (MAXRECURSION 1000);
return ;
end;
Вы можете вызвать эту функцию
select * from split_string('apple,banana,pineapple,grapes',',')