SQL Server - 在搜索时是否有一种简单的方法可以忽略引号?

时间:2012-08-08 18:10:00

标签: sql sql-server

我有一个网站,我需要能够搜索数据并让查询忽略所有引号。

  1. 搜索并检索包含以下字词开头的行的结果:< em>不,
  2. 搜索&#34; hello&#34; “hello” hello 并检索包含单词的行的结果with:&#34; hello&#34; “hello” hello
  3. 注意:我已经删除了传入搜索字词的引号

    我想知道是否有比(

    )更简单(或更简洁)的方法
    select Name 
      from tbl_MyTable
     where (Replace(Replace(Replace(Replace(Replace(Replace(Name,'“',''),'‘',''),'''',''),'"',''),'’',''),'”','') like 'dont%' 
        or Replace(Replace(Replace(Replace(Replace(Replace(Name,'“',''),'‘',''),'''',''),'"',''),'’',''),'”','') like '% dont%' );
    

    现在,我最好的想法是创建一个包含引号剥离版本的新列(前面加一个空格),这样我就可以这样做:

    select Name 
      from tbl_MyTable
     where FixedName like '% dont%';
    

    但我真的想知道如果不创建新专栏就可以实现这一目标并使其有效。

5 个答案:

答案 0 :(得分:1)

使用全文索引而不是LIKE。

创建全文索引:

http://msdn.microsoft.com/en-us/library/ms187317.aspx

CREATE UNIQUE INDEX ix1 ON tbl_MyTable(YourKey); //unique index required
CREATE FULLTEXT CATALOG ft AS DEFAULT; // ft is your freetext catalog name
CREATE FULLTEXT INDEX ON tbl_MyTable(Name) 
   KEY INDEX ix1
   WITH STOPLIST = SYSTEM; // this is your index and allows you to run the command below

然后使用它来运行您的查询:

SELECT Name 
FROM tbl_MyTable 
WHERE FREETEXT(Name, 'dont');

对于这种事情来说,这是最快的技术。如果你使用第三方自由文本引擎,你可以更快,但可能没有必要。

答案 1 :(得分:0)

我建议创建一个用户定义的函数来合并这个逻辑:

CREATE FUNCTION [dbo].[udf_StripQuotes]
(
    @String VARCHAR(MAX)
)  
RETURNS VARCHAR(MAX)
AS  
BEGIN 
    RETURN Replace(
        Replace(
            Replace(
                Replace(
                    Replace(
                        Replace(@String,'“',''),
                    '‘',''),
                '''',''),
            '"',''),
        '’',''),
    '”','')
END
GO

然后看起来像:

select Name 
from tbl_MyTable
where dbo.udf_StripQuotes(name) like '% dont%';

就效率而言,%语句中的前导like将阻止您使用任何索引,这将导致全表扫描...这可能是最大的性能打击这个查询。

然而,就像Aaron澄清的那样,由于调用UDF的开销,这个实现将比原来慢。

如果您可以避开主要的通配符,那么computed column with an index可能会提高效果。

否则,我认为您唯一的另一种选择是实施Full-Text Search

答案 2 :(得分:0)

这不是问题的答案,但作为评论真的很难实现。

如果您打算使用UDF来简化查询本身,请帮自己一个忙,并将函数调用限制为您拥有的行数,而不是加倍。而不是:

 where dbo.udf_StripQuotes(name) like 'dont%' 
  or dbo.udf_StripQuotes(name) like '% dont%' );

这样做:

 where ' ' +  dbo.udf_StripQuotes(name) like '% dont%';

就基本问题而言,我同意迈克尔认为索引计算列可能是最好的,但如果名称列超过900字节则这是不可能的(并且这不会神奇地将扫描转换为搜索,由于通配符,它​​只是不需要调用函数或执行查询中的所有替换调用。)

答案 3 :(得分:0)

在空间或时间上有效吗?

您的第一个解决方案节省空间,但由于每次执行查询时都会对表中的每一行应用多个字符串函数,因此可能会节省时间。

生成列的解决方案空间效率低,但由于应用了一次字符串操作(当您添加列然后插入/更新时),可能会节省时间。

从用户的角度来看,最佳解决方案可能是在生成的列上执行搜索。

答案 4 :(得分:0)

尝试以下操作返回所有名称,不带任何引号或双引号。这样可以防止LIKE语句的必要性,避免使用其他列,并加快查询速度:

SELECT Replace(
    Replace(
        Replace(
            Replace(
                Replace(
                    Replace( Name, '“', ''),
                '‘', ''),
            '''',''),
        '"', ''),
     '’',''),
'”', '') AS Name 
FROM tbl_MyTable