SQL Split函数,用于处理文本限定符之间出现delimeter的字符串?
有几个SQL拆分函数,从循环驱动到使用xml命令,甚至使用数字表。我还没有找到一个支持文本限定符的 使用下面的示例字符串,我希望在、、上拆分,但不希望在双引号或单引号之间拆分 示例数据:SQL Split函数,用于处理文本限定符之间出现delimeter的字符串?,sql,tsql,user-defined-functions,Sql,Tsql,User Defined Functions,有几个SQL拆分函数,从循环驱动到使用xml命令,甚至使用数字表。我还没有找到一个支持文本限定符的 使用下面的示例字符串,我希望在、、上拆分,但不希望在双引号或单引号之间拆分 示例数据: jsmith@anywhere.com, "Sally \"Heat\" Jones" <sally@anywhere.com>, "Mark Jones" <mjones@anywhere.com>, "Stone, Ron" <rstone@anywhere.com>
jsmith@anywhere.com, "Sally \"Heat\" Jones" <sally@anywhere.com>, "Mark Jones" <mjones@anywhere.com>, "Stone, Ron" <rstone@anywhere.com>
应返回一个表:
jsmith@anywhere.com
"Sally \"Heat\" Jones" <sally@anywhere.com>
"Mark Jones" <mjones@anywhere.com>
"Stone, Ron" <rstone@anywhere.com>
我知道这是一个复杂的查询/函数,但任何建议或指导都将不胜感激。这是一个快速解决方案,它不够完美,没有堆栈,因此它将把引号内的逗号作为分隔符
alter function fnSplit
(
@Delim char(1),
@List nvarchar(4000)
)
returns table as
return
with
Strings(PosIdx) as
(
select 1
union all
select PosIdx + 1 from Strings where PosIdx < 4000
)
select
ltrim(rtrim(substring(@List, PosIdx, charindex(@Delim, @List + @Delim, PosIdx) - PosIdx))) as value
from
Strings
where
PosIdx <= convert(int, len(@List))
and substring(@Delim + @List, PosIdx, 1) = @Delim
go
select * from fnSplit(',', 'jsmith@anywhere.com, "Sally \"Heat\" Jones" <sally@anywhere.com>, "Mark Jones" <mjones@anywhere.com>, "Stone, Ron" <rstone@anywhere.com>')
option (maxrecursion 0)
这是一个快速的解决方案,它不够完美,没有堆栈,因此它将把引号内的逗号作为分隔符
alter function fnSplit
(
@Delim char(1),
@List nvarchar(4000)
)
returns table as
return
with
Strings(PosIdx) as
(
select 1
union all
select PosIdx + 1 from Strings where PosIdx < 4000
)
select
ltrim(rtrim(substring(@List, PosIdx, charindex(@Delim, @List + @Delim, PosIdx) - PosIdx))) as value
from
Strings
where
PosIdx <= convert(int, len(@List))
and substring(@Delim + @List, PosIdx, 1) = @Delim
go
select * from fnSplit(',', 'jsmith@anywhere.com, "Sally \"Heat\" Jones" <sally@anywhere.com>, "Mark Jones" <mjones@anywhere.com>, "Stone, Ron" <rstone@anywhere.com>')
option (maxrecursion 0)
以下是我的解决方案:
CREATE FUNCTION fnSplitString
(
@input nvarchar(MAX)
)
RETURNS @emails TABLE
(
email nvarchar(MAX)
)
AS
BEGIN
DECLARE @len int = LEN(@input)
DECLARE @pos int = 1;
DECLARE @start int = 1;
DECLARE @ignore bit = 0;
WHILE(@pos<=@len)
BEGIN
DECLARE @ch nchar(1) = SUBSTRING(@input, @pos, 1);
IF ( @ch = '"' or @ch = '''')
BEGIN
SET @ignore = 1 - @ignore;
END
IF (@ch = ',' AND @ignore = 0)
BEGIN
INSERT @emails VALUES (SUBSTRING(@input, @start, @pos-@start));
SET @start = @pos+1;
END
SET @pos = @pos + 1;
END
IF (@start<>@pos)
BEGIN
INSERT @emails VALUES (SUBSTRING(@input, @start, @pos-@start));
END
RETURN
END
GO
DECLARE @input nvarchar(max) = 'jsmith@anywhere.com, "Sally \"Heat\" Jones" <sally@anywhere.com>, "Mark Jones" <mjones@anywhere.com>, "Stone, Ron" <rstone@anywhere.com>';
select * from fnSplitString(@input)
以下是我的解决方案:
CREATE FUNCTION fnSplitString
(
@input nvarchar(MAX)
)
RETURNS @emails TABLE
(
email nvarchar(MAX)
)
AS
BEGIN
DECLARE @len int = LEN(@input)
DECLARE @pos int = 1;
DECLARE @start int = 1;
DECLARE @ignore bit = 0;
WHILE(@pos<=@len)
BEGIN
DECLARE @ch nchar(1) = SUBSTRING(@input, @pos, 1);
IF ( @ch = '"' or @ch = '''')
BEGIN
SET @ignore = 1 - @ignore;
END
IF (@ch = ',' AND @ignore = 0)
BEGIN
INSERT @emails VALUES (SUBSTRING(@input, @start, @pos-@start));
SET @start = @pos+1;
END
SET @pos = @pos + 1;
END
IF (@start<>@pos)
BEGIN
INSERT @emails VALUES (SUBSTRING(@input, @start, @pos-@start));
END
RETURN
END
GO
DECLARE @input nvarchar(max) = 'jsmith@anywhere.com, "Sally \"Heat\" Jones" <sally@anywhere.com>, "Mark Jones" <mjones@anywhere.com>, "Stone, Ron" <rstone@anywhere.com>';
select * from fnSplitString(@input)
这显然不是解决原来问题的办法。我想在、、上拆分,但不是在双引号或单引号之间拆分。这显然不是原始问题的解决方案。我希望在、、上拆分,但不希望在双引号或单引号之间拆分。