MS SQL Server 在空格上拆分单词,但仅在不在双引号中时

Posted

技术标签:

【中文标题】MS SQL Server 在空格上拆分单词,但仅在不在双引号中时【英文标题】:MS SQL Server split words on spaces but only when not in double-quotes 【发布时间】:2021-12-31 21:10:03 【问题描述】:

我在 SQL 中有以下函数,我曾经从我网站上的搜索页面获取一个 varchar“查询”字符串。它将字符串参数拆分为临时表,其中包含该查询中所有单词的列表。但是,我想结合用户通过将单词括在引号中来搜索短语的能力。因此,在我返回的临时表中,一个阶段基本上会被视为一个词。 所以基本上它现在的工作方式如果你搜索“Gold TV”4K,它会返回类似

“金” 电视” 4K

我希望它返回

黄金电视 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

【问题讨论】:

您的 SQL Server 版本是多少? (select @@version) Microsoft SQL Server 2014 - 12.0.6372.1 (X64) 这在过程语言中要容易得多,TSQL 确实不擅长这种事情。在您的客户端应用程序中执行此操作,并传入不同字符串的表值参数 dbfiddle.uk/… 【参考方案1】:

使用辅助函数和 CROSS APPLY

示例

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 年,这里是我的拆分/解析函数

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)
);

【讨论】:

注入了几个空格..dbfiddle.uk/… @lptr 好奇。我去看看 @lptr 对 WHERE 的小调整解决了重复的空格。 200K 个空间似乎不切实际。 dbfiddle.uk/…【参考方案2】:

这是您的 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]

dbfiddle here

上的演示

【讨论】:

以上是关于MS SQL Server 在空格上拆分单词,但仅在不在双引号中时的主要内容,如果未能解决你的问题,请参考以下文章

拆分音频文件,但仅在暂停中

在将 MS Access 拆分为 SQL Server 以执行查询后使用哪个引擎

RegEx Tokenizer:将文本拆分为单词、数字、标点和空格(不要删除任何内容)

2021-10-15:单词拆分。给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。说明:拆分时可以重复使用字典中的单词。你

用空格(或任何字符)将文本单元格拆分为任意数量的单词,重复单词

将一串空格分隔的单词拆分为多行[重复]