- 类别:
:doc:`/sql-reference/functions-string`(全文搜索)
SEARCH¶
从一个或多个表中搜索指定列中的字符数据(文本),包括 VARIANT、OBJECT 和 ARRAY 列中的字段。文本分析器将文本分解为词元,这些词元是文本的离散单位,例如单词或数字。如果您不指定分析器,则会应用默认分析器。
有关使用此函数的更多信息,请参阅 使用全文搜索。
语法¶
必填实参¶
search_data您要搜索的数据,以字符串字面量、列名或到 VARIANT 列中字段的 路径 的逗号分隔的列表表示。搜索数据也可以是一个单一的字面量字符串,这在测试函数时可能很有用。
您可以指定通配符字符 (
*),其中*扩展为函数范围内所有表中所有符合条件的列。符合条件的列是那些具有 VARCHAR(文本)、VARIANT、ARRAY 和 OBJECT 数据类型的列。VARIANT、ARRAY 和 OBJECT 数据已转换为文本以便搜索。当您将通配符传递给函数时,您可以使用表的名称或别名来限定通配符。例如,要传入名为
mytable的表中的所有列,请指定以下内容:您还可以使用 ILIKE 和 EXCLUDE 关键字进行筛选:
ILIKE 筛选条件,用于查找与指定模式匹配的列名。只允许使用一种模式。例如:
EXCLUDE 筛选出与指定列或列不匹配的列名。例如:
使用这些关键字时,限定符有效。以下示例使用 ILIKE 关键字筛选出与表
mytable中的模式col1%相匹配的所有列:ILIKE 和 EXCLUDE 关键字不能组合在单个函数调用中。
关于 ILIKE 和 EXCLUDE 关键字的更多信息,请参阅 SELECT 中的“参数”部分。
当多个表在范围内时,您可以通过联连表或使用 UNION 集合运算符从多个表中搜索列。要搜索联接或 UNION 查询的输出中的所有列,可以使用不带限定的
*通配符,如下所示:要在联接表时搜索特定列,您可能需要限定列名(例如,
table2.colname)。您还可以使用限定的*通配符,如下所示:然而,您不能为该函数指定
*或table.*超过一次。在前面的联接示例中,您不能指定SEARCH((T1.*, T2.*), 'string')。此语法返回错误。当列出
*、table.*或多个项目时,search_data实参需要括号。例如:如果没有使用括号来分隔多个项目,则逗号会被解析为函数参数之间的分隔符。
另请参阅 预期错误案例的示例。
您可以通过指定列名、冒号或点以及用点分隔的子字段,在 VARIANT 数据中搜索字段。例如:
colname:fieldname.subfieldname。有关在此类列中指定字段的更多信息,请参阅 遍历半结构化数据。'search_string'一个 VARCHAR 字符串,包含一个或多个搜索词。此参数必须是字面量字符串;不支持列名。用一对单引号将整个字符串括起来。不用引号将个别搜索词或短语括起来。例如,请使用:
'blue red green'不要使用:
'blue' 'red' 'green'为 SEARCH_MODE 实参设置
OR或AND时,术语列表可以是“析取”或“合取”关系。但是,当使用'NO_OP_ANALYZER'时,查询字符串将按照原样进行完全匹配,不会划分词元,也没有析取的或合取的语义。搜索不区分大小写(使用
'NO_OP_ANALYZER'时除外),因此对字符串'ONCE'执行搜索词'Once upon a time'搜索会返回 TRUE。当为 SEARCH_MODE 实参设置
OR或AND时,搜索词的顺序并不重要,只要它们在搜索数据中的存在即可。当为 SEARCH_MODE 实参设置PHRASE或EXACT时,搜索词的顺序必须与被搜索数据中的顺序完全一致。
可选实参¶
ANALYZER => 'analyzer_name'文本分析器的名称。名称必须放在单引号内。
分析器将搜索词(以及正在搜索的列中的文本)分解为词元。从搜索字符串中提取的词元和从被搜索的列或字段中提取的词元的匹配语义(析取、合取、短语匹配或完全匹配)取决于 SEARCH_MODE 实参。
分析器对字符串进行标记化处理时,会在发现特定分隔符的地方将其打断。这些分隔符不包括在结果词元中,不会提取空词元。
该参数可接受以下值:
'DEFAULT_ANALYZER'– 根据以下分隔符将文本分解为词元:字符
Unicode 代码
描述
U+0020空格
[U+005B左方括号
]U+005D右方括号
;U+003B分号
<U+003C小于号
>U+003E大于号
(U+0028左括号
)U+0029右括号
{U+007B左花括号
}U+007D右花括号
|U+007C竖线
!U+0021感叹号
,U+002C逗号
'U+0027撇号
"U+0022引号
*U+002A星号
&U+0026和号
?U+003F问号
+U+002B加号
/U+002F斜杠
:U+003A冒号
=U+003D等号
@U+0040@ 号
.U+002E句号
-U+002D连字符
$U+0024美元符号
%U+0025百分号
\U+005C反斜杠
_U+005F下划线(底线)
\nU+000A新行(换行符)
\rU+000D回车
\tU+0009水平制表符
'UNICODE_ANALYZER':基于 Unicode 分割规则进行划分词元处理;这些规则将空格和某些标点符号视为分隔符。这些内部规则旨在支持多种语言的自然语言搜索。例如,默认分析器将 IP 地址中的句点和缩写中的撇号视为分隔符,但 Unicode 分析器则不这样做。请参阅 使用分析器来调整搜索行为。有关 Unicode Text Segmentation 算法的更多信息,请参阅 https://unicode.org/reports/tr29/ (https://unicode.org/reports/tr29/)。
'NO_OP_ANALYZER':既不对数据也不对查询字符串进行划分词元处理。即使查询字符串看起来包含多个词元(例如,FALSE),列或字段也必须完全等于整个查询字符串。即使查询字符串看起来包含多个词元(例如,'sky blue'),列或字段也必须完全等于整个查询字符串。在这种情况下,只有'sky blue'是匹配项;而'sky'和'blue'不是匹配项。
有关不同分析器行为的更多信息,请参阅 如何将搜索词划分为词元。
SEARCH_MODE => { 'OR' | 'AND' | 'PHRASE' | 'EXACT' }搜索使用的语义。将此实参设置为以下值之一:
'OR'– 该函数使用的是析取的语义。如果从被搜索列或字段中提取的 任何 词元与从搜索字符串中提取的 任何 词元相匹配,则会出现匹配。例如,如果search_string值为'blue red green',则对于在被搜索的任何列或字段中包含 TRUEblueORredOR 的行,函数将返回green。'AND'– 该函数使用的是合取的语义。如果从 至少一个 被搜索列或字段中提取的词元与从搜索字符串中提取的 所有 词元相匹配,则会出现匹配。匹配的词元必须都在一列或一个字段中;不能分散在多列或多个字段中。例如,如果search_string值为'blue red green',则对于在至少一个被搜索的列或字段中包含 TRUEblueANDredAND 的行,函数返回green。'PHRASE'– 该函数使用的是短语匹配语义。如果从 至少一个 被搜索列或字段中提取的词元与从搜索字符串中提取的 所有 词元相匹配(包括词元的顺序和相邻关系),则认为匹配成功。匹配语义与合取语义相同,但以下差异除外:
词元的顺序必须完全匹配。例如,如果
search_string值为'blue,red,green',则对于red,green,blue,函数返回 FALSE。搜索数据中不得插入其他词元。例如,如果
search_string值为'blue,red,green',则对于blue,yellow,red,green,函数返回 FALSE。
'EXACT'– 该函数使用的是完全匹配语义。如果从 至少一个 被搜索列或字段中提取的词元与从搜索字符串(包括分隔符)中提取的 所有 词元相匹配,则认为匹配成功。匹配语义与短语搜索语义相同,但以下差异除外:
词元之间的分隔符字符串必须完全匹配。例如,如果
search_string值为'blue,red,green',则对于在至少一个被搜索的列或字段中包含blue,red,green的行,函数返回 TRUE。对于变体(例如blue|red| green或blue, red, green),函数返回 FALSE。当分隔符是
search_string值中的第一个或最后一个字符时,分隔符会被视为匹配字符。因此,第一个和最后一个分隔符左侧和右侧的分隔符也可能导致匹配。例如,如果search_string值为'[blue]',对于foo [blue] bar、[[blue]]`和 :code:`=[blue].,函数返回 TRUE,但不适用于(blue)或foo blue bar。
对于所有搜索模式,字符串的左右两侧必须由分隔符符号分隔。例如,如果
search_string值为'blue,red,green',则对于-blue,red,green;,函数返回 TRUE。对于darkblue,red,green或blue,red,greenish,函数将返回 FALSE。如果您使用
UNICODE_ANALYZER,则不支持完全匹配语义。您可以将DEFAULT_ANALYZER或NO_OP_ANALYZER与完全匹配语义结合使用,但通常此类搜索语义最适用于DEFAULT_ANALYZER。使用
DEFAULT_ANALYZER的完全匹配搜索在以下方面与等值搜索或使用NO_OP_ANALYZER的全文搜索有所不同:等值搜索会匹配列值与谓词中的值完全相同的行(包括字母大小写),且搜索字符串周围不允许有额外文本。
使用
NO_OP_ANALYZER的全文搜索与等值搜索类似,它区分大小写且不允许额外文本。使用
DEFAULT_ANALYZER的完全匹配语义会对列值进行划分词元处理。只要搜索字符串前后出现的额外词元由词元分隔符隔开,即允许存在此类词元。搜索不区分大小写。
默认:
'OR'
返回¶
返回 BOOLEAN:
如果根据 SEARCH_MODE 实参中指定的语义,
search_string词元与search_data词元相匹配,则值为 TRUE。如果任一实参为 NULL,则返回 NULL。
否则返回 FALSE。
使用说明¶
SEARCH 函数仅针对 VARCHAR、VARIANT、ARRAY 和 OBJECT 数据执行操作。如果
search_data实参不包含这些数据类型的数据,则该函数会返回错误。当search_data实参同时包含支持的数据类型和不支持的数据类型时,函数会搜索支持的数据类型的数据,并静默忽略不支持的数据类型的数据。有关示例,请参阅 预期错误案例的示例。您可以使用 ALTER TABLE 命令在作为 SEARCH 函数调用目标的列上添加 FULL_TEXT 搜索优化。例如:
有关更多信息,请参阅 启用 FULL_TEXT 搜索优化。
如何将搜索词划分为词元¶
以下表格展示了一些示例,说明输入搜索词是如何被拆分成标记的,这取决于所使用的分析器所应用的规则。在表格中,逗号表示拆分词元的位置(如果有的话)。
搜索词 |
词元:DEFAULT_ANALYZER |
词元:UNICODE_ANALYZER |
NO_OP_ANALYZER(不拆分) |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
示例¶
以下示例展示了使用 SEARCH 函数的不同方式,从简单用法开始,逐渐过渡到更复杂的用例:
要运行多个示例中的查询,请首先 为 SEARCH 函数创建示例数据。
匹配字面量¶
最简单的 SEARCH 函数的例子是在字符串字面量上对 TRUE 或 FALSE 的测试。第一个示例返回 TRUE,因为第一个和第二个实参的字面量匹配,前提是比较不区分大小写。
第二个示例返回 FALSE,因为在为第一个实参指定的字面量 5.1.33 中没有出现词元 32。
匹配列引用¶
此示例使用表中的一列作为第一个实参。该函数返回 TRUE,因为搜索词之一 (king) 存在于 character 列中。术语列表是析取的,因为 SEARCH_MODE 实参的默认值为 'OR'。(有关此处及后续示例中使用的表的信息,请参阅 为 SEARCH 创建示例数据。)
下面的示例与前面的示例类似,但搜索语义是合取的,因为 SEARCH_MODE 实参设置为 'AND'。该函数返回 FALSE,因为搜索词之一 (king) 仅存在于 character 列中。术语 queen 未出现在搜索数据中。
在一列上搜索 WHERE 子句¶
以下查询使用 SEARCH 函数在 line 列中查找包含单词“wherefore”的行:
在多个列上搜索 WHERE 子句¶
以下查询使用 SEARCH 函数在 play 列和/或 character 列中查找包含单词“king”的行。对于第一个实参,括号是必需的。
在表中对所有符合条件的列进行通配符搜索¶
您可以将 * 字符(或 table.*)用作 SEARCH 函数的第一个实参,如本示例所示。搜索对您选择的表(在本例中为 lines 表)中的所有符合条件的列进行操作。
lines 表有四个列,具有搜索功能支持的数据类型。结果由在四个搜索列中的一个或多个列中出现“king”的行组成。对于其中一列 (act_scene_line),该函数未找到匹配项,但其他三列都有匹配项。SEARCH_MODE 实参默认为 'OR'。
您还可以使用 ILIKE 和 EXCLUDE 关键字进行筛选。有关这些关键字的更多信息,请参阅 SELECT。
此搜索使用 ILIKE 关键字仅在以字符串 line 结尾的列中进行搜索。因此,该函数在 line 和 act_scene_line 列中搜索。
此搜索使用 EXCLUDE 关键字,使得该函数不在 character 列中搜索数据。
在 SELECT 列表中进行通配符搜索¶
您可以在 SELECT 列表中使用 * 字符(或 table.*),如这些示例所示。
以下搜索对您选择的表(在本例中为 lines 表)中的所有符合条件的列进行操作。当 king 出现在四个搜索列中的一个或多个中时,搜索返回 TRUE。SEARCH_MODE 实参默认为 'OR'。
您还可以使用 ILIKE 和 EXCLUDE 关键字进行筛选。有关这些关键字的更多信息,请参阅 SELECT。
此搜索使用 ILIKE 关键字仅在以字符串 line 结尾的列中进行搜索。因此,该函数在 line 和 act_scene_line 列中搜索。
此搜索使用 EXCLUDE 关键字,使得该函数不在 play 或 line 列中搜索数据。
在联接的表中对符合条件的列进行通配符搜索¶
此示例使用了两个小表,其中包含有关汽车型号的信息。表 t1 有两个字符列,表 t2 有三个。您可以创建和加载这些表,如下所示:
针对 t1.* 和 t2.* 执行搜索时,以下两个查询的结果不同。t1 中只有两列符合搜索条件,但 t2 中有三列符合条件。
针对 UNION 子查询的输出执行通配符搜索¶
以下示例使用与前一个示例相同的两个表。在本例中,搜索应用于来自 t3``(它是子查询产生的表)的所有符合条件的列。子查询会计算 ``t1 和 ``t2``(五行)中前三列的 UNION。搜索返回了 UNION 结果中的两个匹配行。
查找匹配多个搜索字符串的行¶
以下示例使用了 SEARCH_MODE 实参来指定合取语义,即当两个搜索词同时出现在同一列中时,才能找到匹配项。要使用合取语义,请将 SEARCH_MODE 实参设置为 'AND'。
当您使用合取语义时,同一列中的两个搜索词必须匹配。例如,以下查询不会返回任何结果,因为术语 KING 和 Rosencrantz 没有出现在搜索数据的任何行的同一列中。
类似的查询使用析取的语义(默认),通过将 SEARCH_MODE 实参设置为 'OR',在搜索数据中查找匹配项。
使用短语匹配和完全匹配语义查找行¶
对于类似但略有不同的用例,您可以使用短语匹配和完全匹配语义
当单词和单词的顺序必须完全匹配,但单词之间的分隔符和空格可以存在差异时,使用短语匹配语义。要使用短语匹配语义,请将 SEARCH_MODE 实参设置为
'PHRASE'。当单词、单词的顺序、单词之间的分隔符以及单词之间的空格必须完全匹配时,使用完全匹配语义。要使用完全匹配语义,请将 SEARCH_MODE 实参设置为
'EXACT'。
以下示例使用短语匹配语义,在较长的文本字符串中查找文本的完全匹配项,但搜索文本中的分隔符不同,并且单词之间存在额外空格:
下面的示例与前一个示例相同,不同之处在于它使用完全匹配语义,在较长的文本字符串中查找文本的完全匹配项:
短语匹配和完全匹配语义的常见用例包括查找电子邮件地址、URLs 和电话号码。在接下来的示例中,请创建一个包含一行示例数据的表:
以下示例通过查询演示三种搜索语义:首次搜索将 SEARCH_MODE 实参设为 'AND' 以使用合取语义检索邮件数据,第二次搜索采用短语匹配语义,第三次搜索则使用完全匹配语义:
输出结果显示如下:
AND搜索返回 TRUE,即使搜索字符串和搜索数据中的术语john、robert和doe顺序不同。PHRASE和EXACT搜索返回 FALSE,因为搜索词的顺序与搜索字符串不匹配。
以下示例通过查询演示三种搜索语义:首次搜索将 SEARCH_MODE 实参设为 'AND' 以使用合取语义检索邮件数据,第二次搜索采用短语匹配语义,第三次搜索则使用完全匹配语义:
输出结果显示如下:
AND搜索返回 TRUE,即使搜索数据中穿插了额外词元robert。PHRASE与EXACT搜索均返回 FALSE,因为当搜索数据中穿插额外词元时,这些搜索语义无法找到匹配项。
以下示例通过运行查询演示:首次搜索使用短语匹配语义检索电子邮件数据,第二次搜索则使用完全匹配语义:
输出显示,PHRASE 搜索返回 TRUE,即使搜索字符串中电子邮件地址的分隔符是连字符,而不是 john、robert 和 doe 之间的句点。EXACT 搜索返回 FALSE,因为在完全匹配语义下,搜索字符串中的分隔符必须与搜索数据完全一致。
以下示例通过运行查询演示:首次搜索使用短语匹配语义检索 URL 数据,第二次搜索则使用完全匹配语义:
输出显示,PHRASE 搜索返回 TRUE,即使搜索字符串中 URL 的分隔符是下划线,而不是产品 ID 中的句点。EXACT 搜索返回 FALSE:
以下示例通过运行查询演示:首次搜索使用短语匹配语义检索电话号码数据,第二次搜索则使用完全匹配语义:
输出显示,PHRASE 搜索返回 TRUE,即使搜索字符串中的电话号码分隔符是句点,而不是连字符。EXACT 搜索返回 FALSE:
以下示例在 WHERE 子句中使用 SEARCH 函数来查询 phrase_exact_search_samples 表。首先,向表中插入另一行数据:
以下示例在表数据中搜索电话号码 800-555-0100 的完全匹配项:
以下示例与前一示例相同,但改用析取语义替代完全匹配语义,从而任何包含 800 或 555 的电话号码都会匹配:
在联接中搜索 VARIANT 和 VARCHAR 数据¶
以下示例显示了 car_rentals 和 car_sales 这两个表的联接,搜索应用于两个表中的列。car_sales 表包含 VARIANT 数据。car_sales 表及其数据在 查询半结构化数据 下描述。以下 SQL 语句创建 car_rentals 表并向其中插入数据:
运行查询:
在这个第二个示例中,针对相同的数据,使用了不同的搜索词:
使用分析器来调整搜索行为¶
以下示例展示了如何通过指定非默认分析器 SEARCH 或 'UNICODE_ANALYZER' 来调整 'NO_OP_ANALYZER' 函数的行为。
第一个示例使用 'NO_OP_ANALYZER' 来测试字符串 1.2.500 是否与 act_scene_line 表的 lines 列中任何行的确切内容匹配。两行都符合搜索条件。
如果您在此示例中移除了 'NO_OP_ANALYZER',让它不再是实参,搜索将返回大量的行。默认分析器将 1、2 和 500 视为不同的词元;因此,对于存在 1、2 或 500 的所有行(无论顺序或组合如何),该函数都返回 TRUE。
如果您将此查询更改为仅包含第二个实参的前缀 1.2,则默认分析器会返回 TRUE,但 'UNICODE_ANALYZER' 和 'NO_OP_ANALYZER' 都返回 FALSE。默认分析器将这些值中的句点视为分隔符,但 Unicode 分析器则不这样做。
以下两个查询展示了使用 'UNICODE_ANALYZER' 而不是默认分析器的另一种效果。第一个查询使用 'UNICODE_ANALYZER',只返回了一行。第二个参数中的额外单引号用于转义表示撇号的单引号。请参阅 单引号字符串常量。
第二个查询使用默认分析器,返回四行,因为默认分析器将撇号字符视为分隔符。任何包含字母 "s" 作为词元的字符串都符合搜索条件。在此示例中,对于包含“撇号 s”的每个字符串 ('s),函数返回 TRUE。
预期错误案例的示例¶
以下示例显示了返回预期语法错误的查询。
此示例失败了,因为 5 不是 search_string 实参支持的数据类型。
此示例失败了,因为不存在为 search_data 实参指定支持的数据类型的列。
此示例成功了,因为存在为 search_data 实参指定支持的数据类型的列。该函数忽略了 line_id 列,因为它不是支持的数据类型
此示例失败了,因为针对第一个实参列出了多个字符串字面量,没有括号,导致实参不匹配:
此示例失败了,因为针对第一个实参列出了多个列名,没有括号,导致实参过多。
此示例失败了,因为不接受列名作为搜索字符串实参。
为 SEARCH 创建示例数据¶
本节中的一些示例查询包含莎士比亚戏剧中的文本的表。每行文本存储在表的单独一行中。其他列标识戏剧的名称、角色的名称等。lines 表具有以下结构:
例如,这个表中的一行看起来像这样:
如果您想运行本节中的示例,请通过运行以下命令创建此表: