MS SQL 服务器按空格拆分单词,但仅当不在双引号中时
MS SQL Server split words on spaces but only when not in double-quotes
我在 SQL 中有以下功能 我曾经从我网站的搜索页面中获取一个 varchar“查询”字符串。它将 String 参数拆分为 temp table 以及该查询中所有单词的列表。但是,我想通过将单词括在引号中来合并用户搜索短语的功能。所以在我的 returned temp table 中,一个阶段基本上被认为是一个词。
所以基本上它现在的工作方式是,如果你搜索“Gold TV”4K,它会 return 类似
- “黄金
- 电视
- 4K
我想 return
- 黄金电视
- 4K
我没能理解正确的逻辑,这是我当前的功能。或者如果有更好的方法让我知道。
CREATE FUNCTION [dbo].[querySplit](@String varchar(8000), @Delimiter char(1))
returns @temptable TABLE (items varchar(8000))
as
begin
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end
使用辅助函数和交叉应用
例子
Declare @S varchar(max) = 'Max "Gold TV" 4K Ultra'
Select Parsed = coalesce(B.RetVal,replace(A.RetVal,'"',''))
From [dbo].[tvf-Str-Parse](replace(replace(' '+@S+' ',' "','|"'),'" ','"|'),'|') A
Cross Apply [dbo].[tvf-Str-Parse] (case when A.RetVal like '%"%' then null else A.RetVal end,' ') B
Where B.RetVal is not null
or charindex('"',A.RetVal)>0
Order By A.RetSeq,B.RetSeq
结果
Parsed
Max
Gold TV
4K
Ultra
因为你是 2014 年,这里是我的 split/parse 函数
CREATE FUNCTION [dbo].[tvf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = row_number() over (order by 1/0)
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
这是经过一些调整的 UDF。
CREATE FUNCTION [dbo].[querySplit] (
@String VARCHAR(8000),
@Delimiter CHAR(1)
)
RETURNS @Tbl TABLE (items VARCHAR(8000))
WITH SCHEMABINDING
AS
BEGIN
DECLARE @idx INT;
DECLARE @slice VARCHAR(8000);
SET @idx = 1;
IF LEN(@String)<1 OR @String IS NULL RETURN;
WHILE @idx != 0
BEGIN
IF LEFT(@String,1) = '"'
BEGIN
SET @String = STUFF(@String, 1, 1, '');
SET @idx = CHARINDEX('"', @String, 2);
END
ELSE
SET @idx = CHARINDEX(@Delimiter, @String);
IF @idx != 0
SET @slice = LEFT(@String, @idx-1);
ELSE
SET @slice = @String;
IF (LEN(@slice)>0)
INSERT INTO @Tbl (Items) VALUES (@slice);
SET @String = RIGHT(@String, LEN(@String) - @idx);
IF LEN(@String) = 0 break;
END
RETURN;
END
select quotename(items)
from dbo.querySplit('"Diamond 3D Goggles" "5 inch×2"', ' ')
(No column name)
[Diamond 3D Goggles]
[5 inch×2]
演示 db<>fiddle here
我在 SQL 中有以下功能 我曾经从我网站的搜索页面中获取一个 varchar“查询”字符串。它将 String 参数拆分为 temp table 以及该查询中所有单词的列表。但是,我想通过将单词括在引号中来合并用户搜索短语的功能。所以在我的 returned temp table 中,一个阶段基本上被认为是一个词。 所以基本上它现在的工作方式是,如果你搜索“Gold TV”4K,它会 return 类似
- “黄金
- 电视
- 4K
我想 return
- 黄金电视
- 4K
我没能理解正确的逻辑,这是我当前的功能。或者如果有更好的方法让我知道。
CREATE FUNCTION [dbo].[querySplit](@String varchar(8000), @Delimiter char(1))
returns @temptable TABLE (items varchar(8000))
as
begin
declare @idx int
declare @slice varchar(8000)
select @idx = 1
if len(@String)<1 or @String is null return
while @idx!= 0
begin
set @idx = charindex(@Delimiter,@String)
if @idx!=0
set @slice = left(@String,@idx - 1)
else
set @slice = @String
if(len(@slice)>0)
insert into @temptable(Items) values(@slice)
set @String = right(@String,len(@String) - @idx)
if len(@String) = 0 break
end
return
end
使用辅助函数和交叉应用
例子
Declare @S varchar(max) = 'Max "Gold TV" 4K Ultra'
Select Parsed = coalesce(B.RetVal,replace(A.RetVal,'"',''))
From [dbo].[tvf-Str-Parse](replace(replace(' '+@S+' ',' "','|"'),'" ','"|'),'|') A
Cross Apply [dbo].[tvf-Str-Parse] (case when A.RetVal like '%"%' then null else A.RetVal end,' ') B
Where B.RetVal is not null
or charindex('"',A.RetVal)>0
Order By A.RetSeq,B.RetSeq
结果
Parsed
Max
Gold TV
4K
Ultra
因为你是 2014 年,这里是我的 split/parse 函数
CREATE FUNCTION [dbo].[tvf-Str-Parse] (@String varchar(max),@Delimiter varchar(10))
Returns Table
As
Return (
Select RetSeq = row_number() over (order by 1/0)
,RetVal = ltrim(rtrim(B.i.value('(./text())[1]', 'varchar(max)')))
From (Select x = Cast('<x>' + replace((Select replace(@String,@Delimiter,'§§Split§§') as [*] For XML Path('')),'§§Split§§','</x><x>')+'</x>' as xml).query('.')) as A
Cross Apply x.nodes('x') AS B(i)
);
这是经过一些调整的 UDF。
CREATE FUNCTION [dbo].[querySplit] ( @String VARCHAR(8000), @Delimiter CHAR(1) ) RETURNS @Tbl TABLE (items VARCHAR(8000)) WITH SCHEMABINDING AS BEGIN DECLARE @idx INT; DECLARE @slice VARCHAR(8000); SET @idx = 1; IF LEN(@String)<1 OR @String IS NULL RETURN; WHILE @idx != 0 BEGIN IF LEFT(@String,1) = '"' BEGIN SET @String = STUFF(@String, 1, 1, ''); SET @idx = CHARINDEX('"', @String, 2); END ELSE SET @idx = CHARINDEX(@Delimiter, @String); IF @idx != 0 SET @slice = LEFT(@String, @idx-1); ELSE SET @slice = @String; IF (LEN(@slice)>0) INSERT INTO @Tbl (Items) VALUES (@slice); SET @String = RIGHT(@String, LEN(@String) - @idx); IF LEN(@String) = 0 break; END RETURN; END
select quotename(items) from dbo.querySplit('"Diamond 3D Goggles" "5 inch×2"', ' ')
(No column name) [Diamond 3D Goggles] [5 inch×2]
演示 db<>fiddle here