CONTAINS (Transact-SQL)

WHERE 子句中的一个谓词,用于在包含字符数据类型的列中搜索单个词和短语的精确或模糊(不太精确)匹配项、一定距离范围内的邻近词或加权匹配项。

在 SQL Server 中,可以在 CONTAINS 或 FREETEXT 全文谓词中使用由四部分组成的名称,对链接服务器执行查询。

CONTAINS 谓词可以搜索:

  • 词或短语。

  • 词或短语的前缀。

  • 与另一个词相邻的词。

  • 由另一个词的词形变化而生成的词(例如,drive 一词是 drives、drove、driving 和 driven 词形变化的词干)。

  • 使用同义词库确定的另一个词的同义词(例如,metal 一词可能有 aluminum 和 steel 等同义词)。

主题链接图标Transact-SQL 语法约定

语法

CONTAINS
      ( { column_name | ( column_list ) | * } 
          , '<contains_search_condition>'     
   [ , LANGUAGE language_term ]
      ) 

<contains_search_condition> ::= 
    { <simple_term> 
    | <prefix_term> 
    | <generation_term> 
    | <proximity_term> 
    | <weighted_term> 
    } 
    | { ( <contains_search_condition> ) 
    [ { <AND> | <AND NOT> | <OR> } ] 
<contains_search_condition> [ ...n ] 
    } 

<simple_term> ::= 
          word | "phrase"

<prefix term> ::= 
     { "word *" | "phrase *" }

<generation_term> ::= 
     FORMSOF ( { INFLECTIONAL | THESAURUS } , <simple_term> [ ,...n ] ) 

<proximity_term> ::= 
     { <simple_term> | <prefix_term> } 
     { { NEAR | ~ }
     { <simple_term> | <prefix_term> } 
     } [ ...n ] 

<weighted_term> ::= 
     ISABOUT 
        ( { { 
    <simple_term> 
  | <prefix_term> 
  | <generation_term> 
  | <proximity_term> 
  } 
   [ WEIGHT ( weight_value ) ] 
   } [ ,...n ] 
        ) 

<AND> ::= 
     { AND | & }

<AND NOT> ::= 
     { AND NOT | &! }

<OR> ::= 
     { OR | | }

参数

  • column_name
    FROM 子句中所指定的表的全文索引列的名称。这些列可为 char、varchar、nchar、nvarchar、text、ntext、image、xml、varbinary 或 varbinary(max) 类型。

  • column_list
    指定以逗号分隔的两个或更多个列。column_list 必须括在括号内。除非指定 language_term,否则 column_list 中所有列的语言必须相同。

  • *
    指定查询将按给定的搜索条件在 FROM 子句中指定的表中搜索所有全文索引列。CONTAINS 子句中的列必须来自包含全文索引的单个表。除非指定 language_term,否则表的所有列的语言都必须相同。

  • LANGUAGE language_term
    查询中用于断字、词干分析、同义词库扩展和替换,以及干扰词(或非索引字)删除的语言。此参数可选。

    如果将采用不同语言的文档一起作为二进制大型对象 (BLOB) 存储在单个列中,则给定文档的区域设置标识符 (LCID) 将决定为其内容编制索引时使用的语言。在对这种列进行查询时,指定 LANGUAGE language_term 可增大找到有效匹配项的可能性。

    language_term 可指定为与语言的 LCID 相对应的字符串、整数或十六进制值。如果指定了 language_term,则其表示的语言将应用于搜索条件的所有元素。如果未指定值,则使用该列的全文语言。

    如果指定为字符串,language_term 将对应于 sys.syslanguages (Transact-SQL) 兼容性视图中的 alias 列值。字符串必须用单引号引起来,如 'language_term'。如果指定为整数,则 language_term 就是标识该语言的实际 LCID。如果指定为十六进制值,则 language_term 将以 0x 开头,后跟 LCID 的十六进制值。十六进制值不能超过八位(包括前导零在内)。

    如果该值是双字节字符集 (DBCS) 格式,则 SQL Server 会将其转换为 Unicode 格式。

    如果指定的语言无效,或者未安装对应于该语言的资源,SQL Server 将返回错误。若要使用非特定语言资源,请将 language_term 指定为 0x0。

  • <contains_search_condition>
    指定要在 column_name 中搜索的文本和匹配条件。

    <contains_search_condition> 的数据类型为 nvarchar。将另一个字符数据类型用作输入时,将发生隐式转换。在下面的示例中,@SearchWord 变量(被定义为 varchar(30))导致 CONTAINS 谓词中发生隐式转换。

    USE AdventureWorks;
    GO
    DECLARE @SearchWord varchar(30)
    SET @SearchWord ='performance'
    SELECT Description 
    FROM Production.ProductDescription 
    WHERE CONTAINS(Description, @SearchWord);
    

    由于“参数截取”跨转换无效,因此请使用 nvarchar 以获得更好的性能。本示例将 @SearchWord 声明为 nvarchar(30)。

    USE AdventureWorks;
    GO
    DECLARE @SearchWord nvarchar(30)
    SET @SearchWord = N'performance'
    SELECT Description 
    FROM Production.ProductDescription 
    WHERE CONTAINS(Description, @SearchWord);
    

    对于生成非最佳计划的情况,还可以使用 OPTIMIZE FOR 查询提示。

  • word
    不带空格或标点符号的字符串。

  • phrase
    在每个词之间有空格的一个或多个词。

    注意注意

    某些语言(如亚洲一些地区的书面语言)的短语可以由彼此之间没有空格的一个或多个词组成。

  • <simple_term>
    指定词或短语的完全匹配项。有效的简单字词示例有 "blue berry"、blueberry 和 "Microsoft SQL Server"。应该使用双引号 ("") 将短语括起来。短语中的词在数据库列中出现的顺序必须与 <contains_search_condition> 中指定的顺序相同。搜索词或短语中的字符时不区分大小写。在全文索引中,不会存储全文索引列中的干扰词(或非索引字),例如 a、and 或 the。如果在单个词搜索中使用了干扰词,SQL Server 将返回错误消息,指出查询仅包含干扰词。SQL Server 在每个 SQL Server 实例的 \Mssql\Binn\FTERef 目录下有一个标准的干扰词列表。

    标点将被忽略。因此,CONTAINS(testing, "computer failure") 将匹配包含 "Where is my computer? Failure to find it would be expensive" 这个值的行。有关断字符行为的详细信息,请参阅断字符和词干分析器

  • <prefix_term>
    指定以指定文本开始的词或短语的匹配项。将前缀字词用英文双引号 ("") 引起来,并在右引号前添加一个星号 (*),这样一来,以星号前指定的简单字词开头的所有文本都将被匹配。该子句应按以下方式指定:CONTAINS (column, '"text*"')。星号可匹配词或短语所含根词的 0 个、1 个或多个字符。如果文本和星号不用英文双引号分隔,则谓词将读取 CONTAINS (column, 'text*'),全文搜索会将星号看作字符,搜索 text* 的完全匹配项。由于断字符通常忽略 (*) 这样的字符,因此全文引擎将不会查找带此类字符的词。

    如果 <prefix_term> 是一个短语,则该短语中包含的每个词都将被看成一个单独的前缀。因此,指定了一个 "local wine*" 前缀字词的查询,将匹配所有包含 "local winery"、"locally wined and dined" 等文本的行。

  • <generation_term>
    包含的简单字词包括要搜索的原始词的变体时,指定词的匹配项。

  • INFLECTIONAL
    指定要对指定的简单字词使用与语言相关的词干分析器。词干分析器的行为是根据每种具体语言的词干确定规则定义的。非特定语言没有关联的词干分析器。使用被查询的列的列语言来引用所需的词干分析器。如果指定了 language_term,则使用与该语言对应的词干分析器。

    <generation_term> 中给定的 <simple_term> 不会同时匹配名词和动词。

  • THESAURUS
    指定使用对应于列全文语言或指定的查询语言的同义词库。最长模式或来自 <simple_term> 的模式将与同义词库匹配,并生成其他字词以扩展或替换原始模式。如果找不到与 <simple_term> 完全或部分匹配的匹配项,不匹配部分将被视为 simple_term。有关全文搜索同义词库的详细信息,请参阅同义词库配置

  • <proximity_term>
    指定词或短语的匹配项必须处于所搜索的文档中。与 AND 运算符类似,<proximity_term> 也要求这两个搜索词都存在于所搜索的文档中。

    • NEAR | ~
      指示 NEAR 或 ~ 运算符两侧的词或短语必须存在于某个文档中,才能返回匹配项。可将多个邻近词链接起来,例如 a NEAR b NEAR c 或 a ~ b ~ c。链在一起的邻近词必须都存在于某个文档中,才能返回匹配项。

      在用于 CONTAINSTABLE 函数中时,搜索词的邻近程度会影响每个文档的排名。文档中匹配的搜索词越接近,该文档的排名就越高。如果匹配的搜索词与源词相隔 50 个词以上,则对该文档返回的排名为 0。

      例如,CONTAINS (column_name, 'fox NEAR chicken') 和 CONTAINSTABLE (table_name, column_name, 'fox ~ chicken') 都将返回指定列中同时包含“fox”和“chicken”的所有文档。此外,CONTAINSTABLE 还会按照 "fox" 和 "chicken" 的邻近程度返回每个文档的排名。例如,如果某文档包含“The fox ate the chicken”这句话,则该文档的排名将很高。

      NEAR 指示字词之间的逻辑距离,而非它们之间的绝对距离。例如,某一段落内其他短语或句子中的字词被视为距离远于同一短语或句子中的字词,而与其实际临近情况无关,因为假定它们是不相关的。同样,不同段落中的字词被视为距离更远。

  • <weighted_term>
    指定(由查询返回的)匹配行与一组词和短语匹配,每个词和短语有一个可选的加权值。

  • ISABOUT
    指定 <weighted_term> 关键字。

    • WEIGHT(weight_value)
      指定介于 0.0 和 1.0 之间的加权值。<weighted_term> 中的每个组件都可以包含一个 weight_value。通过 weight_value 可更改查询的各个部分如何影响赋予与查询匹配的每个行的排名值。WEIGHT 不影响 CONTAINS 查询的结果,但 WEIGHT 会影响 CONTAINSTABLE 查询中的排名。

      注意注意

      不管操作系统的区域设置如何,小数点分隔符始终为句点。

  • { AND | & } | { AND NOT | &!} | { OR | | }
    指定两个包含搜索条件之间的逻辑运算。

    • AND | &
      指示匹配项必须满足这两个包含搜索条件。可以使用 And 符 (&) 代替关键字 AND 来表示 AND 运算符。

    • AND NOT | &!
      指示匹配项中不能出现第二个搜索条件。可使用“与”符号后跟感叹号 (&!) 代替关键字 AND NOT 来表示 AND NOT 运算符。

    • OR | |
      指示匹配项必须满足这两个包含搜索条件之一。可以使用竖线符号 (|) 代替关键字 OR 来表示 OR 运算符。

      如果 <contains_search_condition> 包含带括号的组,则首先计算这些带括号的组。计算了带括号的组之后,将这些逻辑运算符用于包含搜索条件时,适用以下规则:

      • NOT 用在 AND 之前。

      • NOT 仅在 AND NOT 中出现在 AND 之后。不允许使用 OR NOT 运算符。不能在首个字词前指定 NOT。例如,CONTAINS (mycolumn, 'NOT "phrase_to_search_for" ' ) 就是无效的。

      • AND 用在 OR 之前。

      • 相同类型的 Boolean 运算符(AND、OR)可以结合使用,因此可以按任意顺序应用。

      • n
        一个占位符,指示可在其中指定多个 CONTAINS 搜索条件和搜索词。

注释

全文谓词和函数作用于 FROM 谓词所示的单个表。若要对多个表进行搜索,请在 FROM 子句中使用联接表,以搜索由两个或更多个表的乘积构成的结果集。

如果兼容级别小于 70,则不将 CONTAINS 视为关键字。有关详细信息,请参阅 sp_dbcmptlevel (Transact-SQL)

当数据库兼容级别设置为 100 时,不允许在 OUTPUT 子句中使用全文谓词。

LIKE 与全文搜索的比较

与全文搜索不同,LIKETransact-SQL 谓词仅对字符模式有效。另外,不能使用 LIKE 谓词来查询格式化的二进制数据。此外,对大量非结构化的文本数据执行 LIKE 查询要比对相同数据执行同样的全文查询慢得多。对数百万行文本数据进行的 LIKE 查询可能需要几分钟的时间才能返回结果;而对于同样的数据,全文查询只需要几秒甚至更少的时间,具体取决于返回的行数。

示例

A. 使用 CONTAINS 和 <simple_term>

下面的示例将查找包含 "Mountain" 一词且价格为 $80.99 的所有产品。

USE AdventureWorks;
GO
SELECT Name, ListPrice
FROM Production.Product
WHERE ListPrice = 80.99
   AND CONTAINS(Name, 'Mountain');
GO

B. 使用 CONTAINS 和以 <simple_term> 表示的短语

下面的示例将返回包含短语 "Mountain" 或 "Road" 的所有产品。

USE AdventureWorks;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Mountain" OR "Road" ')
GO

C. 使用 CONTAINS 和 <prefix_term>

下面的示例返回的所有产品名称中,其 Name 列中至少有一个词以前辍 chain 开头。

USE AdventureWorks;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, ' "Chain*" ');
GO

D. 使用 CONTAINS 和 OR 以及 <prefix_term>

下面的示例将返回包含以 "chain" 或 "full" 为前缀的字符串的所有类别说明。

USE AdventureWorks;
GO
SELECT Name
FROM Production.Product
WHERE CONTAINS(Name, '"chain*" OR "full*"');
GO

E. 使用 CONTAINS 和 <proximity_term>

下面的示例返回包含 bike 和 performance,并且这两个词相邻的所有产品名称。

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE CONTAINS(Description, 'bike NEAR performance');
GO

F. 使用 CONTAINS 和 <generation_term>

下面的示例将搜索包含单词 ride 的各种形式(如 riding 和 ridden 等)的所有产品。

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE CONTAINS(Description, ' FORMSOF (INFLECTIONAL, ride) ');
GO

G. 使用 CONTAINS 和 <weighted_term>

下面的示例将搜索包含单词 performance、comfortable 或 smooth 以及给定每个词的不同加权的所有产品名称。

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE CONTAINS(Description, 'ISABOUT (performance weight (.8), 
comfortable weight (.4), smooth weight (.2) )' );
GO

H. 使用 CONTAINS 和变量

下面的示例使用了变量来取代具体的搜索项。

USE AdventureWorks;
GO
DECLARE @SearchWord nvarchar(30)
SET @SearchWord = N'Performance'
SELECT Description 
FROM Production.ProductDescription 
WHERE CONTAINS(Description, @SearchWord);
GO

I. 使用 CONTAINS 和逻辑运算符 (AND)

下面的示例使用 AdventureWorks 数据库的 ProductDescription 表。该查询使用 CONTAINS 谓词搜索 ID 不等于 5 并且既包含词“Aluminum”又包含词“spindle”的说明。该搜索条件使用 AND 布尔运算符。

USE AdventureWorks;
GO
SELECT Description
FROM Production.ProductDescription
WHERE ProductDescriptionID <> 5 AND
   CONTAINS(Description, ' Aluminum AND spindle');
GO

J. 使用 CONTAINS 验证行插入操作

下面的示例在 SELECT 子查询中使用 CONTAINS。该查询将使用 AdventureWorks 数据库获取 ProductReview 表中针对某一特定循环的所有注释的注释值。该搜索条件使用 AND 布尔运算符。

USE AdventureWorks;
GO
INSERT INTO Production.ProductReview 
(ProductID, ReviewerName, EmailAddress, Rating, Comments) 
VALUES
(780, 'John Smith', 'john@fourthcoffee.com', 5, 
'The Mountain-200 Silver from AdventureWorks Cycles meets and exceeds expectations. I enjoyed the smooth ride down the roads of Redmond')
 
-- Given the full-text catalog for these tables is Adv_ft_ctlg, 
-- with change_tracking on so that the full-text indexes are updated automatically.
WAITFOR DELAY '00:00:30'   
-- Wait 30 seconds to make sure that the full-text index gets updated.
 
SELECT r.Comments, p.Name
FROM Production.ProductReview r
JOIN Production.Product p 
ON
 r.ProductID = p.ProductID
 
AND r.ProductID = (SELECT ProductID
                  FROM Production.ProductReview
                  WHERE CONTAINS (Comments, 
                                 ' AdventureWorks AND 
                                   Redmond AND 
                                   "Mountain-200 Silver" '))

GO