1.前言
本章包括:
全文索引的介绍
全文索引中的术语
全文索引的体系结构
全文目录的管理
全文索引的管理
填充全文索引
使用全文搜索查询数据
在数据库中快速搜索数据,使用索引可以提高搜索速度,然而索引一般是建立在数字型或长度比较短的文本型字段上的,比如说编号、姓名等字段,如果建立在长度比较长的文本型字段上,更新索引将会花销很多的时间。如在文章内容字段里用like语句搜索一个关键字,当数据表里的内容很多时,这个时间可能会让人难以忍受。
在SQL Server中提供了一种名为全文索引的技术,可以大大提高从长字符串里搜索数据的速度,在本章里,将会对全文索引进行详细的介绍。
14.1 全文索引的介绍
全文索引与普通的索引不同,普通的索引是以B-tree结构来维护的,而全文索引是一种特殊类型的基于标记的功能性索引,是由Microsoft SQL Server全文引擎服务创建和维护的。
使用全文索引可以快速、灵活地为存储在SQL Server数据库中的文本数据创建基于关键字查询的索引,与like语句不同,like语句的搜索是适用于字符模式的查询,而全文索引是根据特定语言的规则对词和短语的搜索,是针对语言的搜索。
在对大量的文本数据进行查询时,全文索引可以大大地提高查询的性能,如对于几百万条记录的文本数据进行like查询可能要花几分钟才能返回结果,而使用全文索引则只要几秒钟甚至更少的时间就可以返回结果了。
14.2 全文索引中常用的术语
由于全文索引中使用了较多的新的术语,在此先介绍这些术语:
l 全文索引:一种特殊的索引,能在给定的列中存储有关重要的词及位置的信息,使用这些信息可以快速进行全文查询,搜索包括特定词或词组的行。
l 全文目录:全文目录是存储全文索引的地方,全文目录必须驻留在与SQL Server实例相关联的本地硬盘上,每个全文目录可用于满足数据库内的一个或多个表的索引需求。
l 断字符与词干分析器:断字符与词干分析器都是用于对全文索引的数据进行语言分析的。语言分析通常都会涉及到查找词的边界和组合动词两个方面,其中要查找词的边界,也就是确定哪几个字符是“词”,称之为“断字”。组合动词也就是词干分析,用于分析词。根据语言的不同,语言分析规则也不尽相同,由此可以为每个全文索引列指定不同的语言。每种语言的断字符能够使得访问语言生成的词更为准确。
l 标记:由断字符标识的词或字符串。
l 筛选器:用于从存储在varbinary(max)或image列中的文件内提取指定的文本类型的文本。当varbinary(max)或image列中包含带有特定文件扩展名的文档时,全文搜索会使用筛选器来解释二进制数据,筛选器会从文档中提取文本化信息并用于建立索引。
l 填充(爬网):创建维护全文索引的过程叫填充,也叫爬网。
l 干扰词:经常出现,但又不是要搜索的词。为了精简全文索引,这些词通常会被忽略。
14.3 全文索引的体系结构
SQL Server的全文索引是由SQL Server FullText Search服务来维护的,该服务可以在Windows操作系统的【管理工具】à【服务】里找到,如图14.1所示,在此可以启动、停止、暂停、恢复和重新启动该服务。只有SQL Server FullText Search服务在启动状态时,才能使用全文索引。
图14.1 SQL Server FullText Search服务
SQL Server FullText Search服务由两个部分组件支持:一个是Microsoft Full-Text Engine for SQL Server(MSFTESQL),也就是SQL Server全文搜索引擎;另一个是Microsoft Full-Text Engine Filter Deamon(MSFTEFD),也就是全文搜索引擎过滤器。
Microsoft Full-Text Engine for SQL Server的作用是填充全文索引、管理全文索引和全文目录、帮助对SQL Server数据库中的数据表进行全文搜索。Microsoft Full-Text Engine Filter Deamon包含筛选器、协议处理程序和断字符三个组件,其作用是负责从数据表中访问和筛选数据以及进行断字和词干分析。其中,筛选器的作用是从文档中提取文本信息,并将非文本信息和格式化信息(如换行符、字体大小等信息)删除,然后生成文本字符串和属性的对应,并将它们传递给索引引擎;协议处理程序用于从指定数据库中的表内访问数据;断字符用于在查询或抓取的文档中确定字符边界位置。
全文索引组件负责对全文索引的初始填充以及当全文索引表中的数据被修改时的更新。当全文填充(爬网)开始后,数据库引擎会将大量的数据存储到内存里,并通知Microsoft Full-Text Engine for SQL Server(MSFTESQL)开始进行索引。当MSFTESQL服务接到进行索引的通知后,使用协议处理程序组件从内存中取得数据进行处理后生成全文索引。MSFTESQL服务会将数据表中的某一列或几列中的字符和二进制数据编制成索引。在对varbinary(max)或image列中的数据编制索引时,筛选器会将基于为该数据指定的文件格式来提取文本。在处理索引的过程中MSFTESQL服务通过断字符来将收集到的文本数据分隔成各个单独的标记或关键字。这个过程就是全文索引的过程。
由于全文索引与普通的索引不同,全文索引并不是存储在数据表中,而是存储在全文目录中,所以在使用全文索引来搜索数据时,其运行的流程和普通索引也不一样。
如图14.2所示,当SQL Server发出全文搜索的请求后,会将搜索的条件传递给全文搜索引擎过滤器,经过MSFTEFD处理后,将数据提供给MSFTESQL,再由MSFTESQL从全文目录中找到符合要求的数据,再返回给SQL Server进行后续操作。这就是进行全文搜索的过程。
图14.2 全文搜索流程
14.4 全文目录管理
在前面章节里提到,全文目录的作用是存储全文索引,所以要创建全文索引必须先创建全文目录。
14.4.1 创建全文目录
创建全文目录的方法如下:
(1)启动【SQL Server Management Studio】,连接到本地默认实例,在【对象资源管理器】窗口里,选择本地数据库实例à【数据库】à【Northwind】à【存储】à【全文目录】。
(2)右击【全文目录】,在弹出的快捷菜单里选择【新建全文目录】选项。
(3)弹出如图14.3所示的【新建全文目录】对话框,在该对话框的【全文目录名称】文本框内可以输入全文目录的名称;在【目录位置】文本框内可以输入全文目录的存储路径,单击其后的【…】按钮可以选择路径,如果不输入的话,默认存储在“Program Files"Microsoft SQL Server"MSSQL.1"MSSQL"FTData”目录下;在【文件组】下拉列表框里可以选择全文目录所属的文件组;在【所有者】文本框里可以输入全文目录的所有者;选中【设置为默认目录】复选框可以将此目录设置为全文目录的默认目录;【区分重音】单选框用于指明目录是否区分标注字符。
图14.3 【新建全文目录】对话框
(4)设置完毕后单击【确定】按钮完成操作。
14.4.2 查看与修改全文目录
全文目录添加完毕之后,可以在【对象资源管理器】窗口的【全文目录】树下看到新建的全文目录。双击该全文目录,或右击该全文目录,在弹出的快捷菜单里选择【属性】选项,将会弹出如图14.4所示【全文目录属性】对话框,在该对话框里可以查看全文目录的属性内容。
在【全文目录属性】对话框里有三个标签:【常规】选项卡里可以查看和修改全文目录的设置;【表/视图】选项里可以查看和修改为全文目录分配的表和视图;【填充计划】选项项里可以添加或修改确定何时填充或重新填充全文目录的计划。
在如图14.4所示的【全文目录属性】对话框里,可以看到全文目录所属的文件组、名称、上次填充的时间、项计数、填充状态、目录大小、唯一键计数的内容,这些内容是不能修改的。可以修改项为:【默认目录】、【所有者】和【区分重音】三个选项内容。
图14.4 查看全文目录属性
在【目录】操作区域,有三个单选按钮,其中【无】表示不执行优化目录、重新生成目录和重新填充目录操作;选择【优化目录】选项将会优化目录的空间利用率、提高搜索结果相关排名的准确性,从而提高查询性能;选择【重新生成目录】选项将会删除并重新生成全文目录,如果对全文目录的属性进行了更改,则必须执行该操作,例如在本对话框中修改了区分重音选择,则【目录】操作区域会自动变成灰色,系统自动重新生成全文目录;选择【重新填充目录】选项将会使用数据的最新更改来更新目录。修改完毕之后,单击【确定】按钮完成操作。
14.4.3 删除全文目录
当全文目录不再需要使用时,可以将其删除,删除方式如下:
(1)启动【SQL Server Management Studio】,连接到本地默认实例,在【对象资源管理器】窗口里,选择本地数据库实例à【数据库】à【Northwind】à【存储】à【全文目录】。
(2)右击要删除的全文目录名,在弹出的快捷菜单里选择【删除】选项。
(3)在弹出的【对象删除】对话框中单击【确定】按钮完成操作。
如果要一次性删除多个全文目录,可以先在【对象资源管理器】窗口中定位到【全文目录】树,在【摘要】对话框里选择多个全文目录,然后单击鼠标右键,在弹出的快捷菜单里选择【删除】选项。在弹出的【对象删除】对话框中单击【确定】按钮完成操作。
14.5 全文索引管理
在创建完全文目录之后,可以动手创建全文索引了,下面将介绍如何创建、编辑和删除全文索引。
14.5.1 创建全文索引的注意事项
在创建全文索引之前,先介绍创建全文索引要注意的事项:
l 全文索引是针对数据表的,只能对数据表创建全文索引,不能对数据库创建全文索引。
l 在一个数据库中可以创建多个全文目录,每个全文目录都可以存储一个或多个全文索引,但是每一个数据表只能够创建一个全文索引,一个全文索引中可以包含多个字段。
l 要创建全文索引的数据表必须要有一个唯一的针对单列的非空索引,也就是说,必须要有主键,或者是具备唯一性的非空索引,并且这个主键或具有唯一性的非空索引只能是一个字段,不能是多字段的组合。
l 包含在全文索引里的字段只能是字符型的或image型的字段。
14.5.2 创建全文索引
下面以Northwind数据的“文章”表为例,介绍如何创建全文索引:
(1)启动【SQL Server Management Studio】,连接到本地默认实例,在【对象资源管理器】窗口里,选择本地数据库实例à【数据库】à【Northwind】à【表】à【文章】。
(2)右击【文章】数据表,在弹出的快捷菜单里选择【全文索引】à【定义全文索引】。
(3)弹出如图14.5所示【全文索引向导】对话框,此对话框中显示的是全文索引向导的介绍,单击【下一步】按钮。
图14.5 【全文索引向导】对话框
(4)弹出如图14.6所示的【选择索引】对话框,此时可以选择要创建全文索引的数据表的唯一索引,使用该索引作为全文索引的唯一索引。在【唯一索引】下拉列表框里,列出该表中所有的唯一索引。在该对话框里选择唯一索引后,单击【下一步】按钮。
图14.6 【选择索引】对话框
(5)弹出如图14.7所示【选择表列】对话框,此时可以选择要加入全文索引的字段。在该对话框里可以选择一个或多个字段加入全文索引。SQL Server 2005可以对存储在image类型的字段中的文件进行全文搜索。image类型的字段中可以存入各种文件,但是SQL Server 2005只支持Word、Excel、PowerPoint、网页和纯文本文件类型。如果要对image类型的字段里的文件进行全文搜索,必须还要有一个字符串类型的字段用于指明存储在image字段中的文件的扩展名。如图14.7中的文件字段,如果要对其创建全文索引,必须还要指定类型列。选择完毕后单击【下一步】按钮。
图14.7 【选择表列】对话框
(6)弹出【选择更改跟踪】对话框,在该对话框里可以定义全文索引的更新方式,一共有三种更新方式:
l 【自动】:选中此单选按钮后,当基础数据发生更改时,全文索引将自动更新;
l 【手动】:如果不希望基础数据发生更改时自动更新全文索引,请选中此单选按钮。对基础数据的更改将保留下来。不过,若要将更改应用到全文索引,必须手动启动或安排此进程;
l 【不跟踪更改】:如果不希望使用基础数据的更改对全文索引进行更新,请选中此单选按钮。
设置完毕后单击【下一步】按钮。
图14.8 【选择更改跟踪】对话框
(7)弹出如图14.9所示的【选择目录】对话框,在此可以选择全文索引所存储的全文目录。如果没有要选择的全文目录,也可以在此新建一个全文目录。创建全文目录的方法与上节中所说的一样。选择完毕后单击【下一步】按钮。
图14.9 【选择目录】对话框
(8)弹出如图14.10所示的【定义填充计划】对话框,在此可以创建全文索引和全文目录的填充计划,也可以单击【下一步】,在创建完全文索引后再创建填充计划。
图14.10 【定义填充计划】对话框
(9)弹出如图14.11所示的【全文索引向导说明】对话框,在该对话框里可以看到全文索引要完成的工作说明,如果有不正确的设置,可以单击【上一步】按钮返回去重新设置,如果完全正确则单击【完成】按钮完成操作。
图14.11 【全文索引向导说明】对话框
14.5.3 查看与修改全文索引
在创建完全文索引之后,右击数据表,在弹出的快捷菜单里选择【全文索引】à【属性】可以查看全文索引的设置,如图14.12所示。
图14.12 【全文索引属性】常规信息对话框
在图14.12中可以看到全文索引的目前设置情况,在该对话框中可以修改是否启用全文索引和全文索引的更改跟踪信息。单击【列】标签,打开如图14.13所示的全文索引的列信息,在此可以修改全文索引所包含的列信息。
图14.13 【列】选项卡
14.5.4 启用和禁用全文索引
全文索引创建完毕之后,不会立即自动启用,所以需要手动启用全文索引。启动全文索引的方法如下:
(1)在【对象资源管理器】窗口里展开树形目录,定位到要启用全文索引的数据表。
(2)右击要启用全文索引的数据表,在弹出的快捷菜单中选择【全文索引】à【启用全文索引】。
如果要禁用全文索引,也可以采取以下的方法来禁用全文索引:
(1)在【对象资源管理器】窗口里展开树形目录,定位到要启用全文索引的数据表。
(2)右击要禁用全文索引的数据表,在弹出的快捷菜单中选择【全文索引】à【禁用全文索引】。
14.5.5 删除全文索引
当全文索引不再使用时,可以将其删除,删除方法如下:
(1)右击要删除全文索引的数据表,在弹出的快捷菜单里选择【全文索引】à【删除全文索引】。
(2)在弹出的【删除全文索引】对话框里单击【确定】按钮完成操作。
14.6 填充全文索引
填充全文索引实质上就是更新全文索引,其目的是让全文索引可能够反映最新的数据表内容。
14.6.1 填充全文索引的方式
填充全文索引一共有三种方式:
l 完全填充:完全填充方式通常发生在首次填充全文目录或全文索引时,在前一节中所说到的“启用全文索引”时,就已经对全文索引进行了一次完全填充,以后就可以使用基于更改跟踪的填充和基于增量时间戳的填充来维护全文索引。
l 基于更改跟踪方式的填充:SQL Server会记录设置了全文索引的数据表中修改的行,这些记录存储在日志中,在某个适当时机时将这些更改填入到全文索引中。
l 基于增量时间戳方式的填充:也就是增量填充,在全文索引中更新上次填充之后更新的行。增量填充要求索引表中必须有timestamp数据类型的字段,如果没有该类型的字段,则无法执行增量填充,系统将会以完全填充的方式来取代增量填充方式进行填充。
14.6.2 填充全文索引
由于填充全文索引有三种不同的方式,所以填充全文索引的方法也不相同。如果要以完全填充或增量填充方式来填充全文索引,则只要右击全文索引所在的数据表,在弹出的快捷菜单里选择【全文索引】à【启动完全填充】或【启动增量填充】选项即可。如图14.14所示。
图14.14 填充全文索引
更改跟踪方式填充全文索引分为手动和自动两种方法,在默认情况下是自动填充,如果要更改为手动方式,可以右击全文索引所在的数据表,在弹出的快捷菜单里选择【全文索引】à【手动跟踪更改】选项,如图14.14所示。
选择完毕之后,SQL Server会自动跟踪数据表中的数据更改情况,但并不将其更新到全文索引中,只有在需要将这些更新反应到全文索引上时,右击全文索引所在的数据表,在弹出的快捷菜单里选择【全文索引】à【应用跟踪的更改】选项后,才会将更新反应到全文索引上。
如果在图14.14所示界面里选择了【自动跟踪更改】选项,则由SQL Server自动将记录的数据表的更改更新到全文索引中,不再需要人工进行填充。
如果在数据库中有多个数据表创建了全文索引,可以使用重新生成索引目录的方法将所有的全文索引进行完全填充,其方法如下:
(1)在【对象资源管理器】窗口里展开树形目录,定位到【服务器】à【数据库】à【Northwind】à【存储】à【全文目录】。
(2)右击【全文目录】,在弹出的快捷菜单中选择【全部重新生成】选项。
(3)在弹出的【重新生成所有全文目录】对话框里单击【确定】按钮完成操作。
14.6.3 定时填充全文索引
在SQL Server 2005中,可以为填充全文索引设置计划,让系统自动定时填充全文索引,其方法如下:
(1)右击全文索引所在的数据表,在弹出的快捷菜单里选择【全文索引】à【属性】来查看全文索引的设置,如图14.12所示,在该图中选择【计划】选项。
(2)弹出如图14.15所示全文索引填充计划对话框,在该对话框中单击【新建】按钮。
图14.15 全文索引填充计划对话框
(3)弹出如图14.16所示的【新建全文索引表计划】对话框。
l 在【名称】文本框里可以输入该计划名称。
l 在【计划类型】下拉列表框里,可选项有“SQL Server代理启动时自动启动”:也就是在SQL Server代理启动时自动填充全文索引;“CPU空闲时启动”:也就是当CPU空闲时填充全文索引;“执行一次”:在指定时间时填充全文索引,只填充一次;“重复执行”:可以设定多次填充全文索引的方式。
l 如果选中【已启用】复选框,则启用该填充全文索引的计划。
l 在【执行一次】区域里,可以设置计划类型为“执行一次”的执行时间,在到达该时间时,自动填充全文索引。
l 在【频率】区域里,可以设置计划类型为“重复执行”的执行频率。在【执行】下拉列表框里可选择项为“每天”、“每周”和“每月”,分别用于指定每天、每周和每月执行填充计划的频率。
l 在【持续时间】区域里可以设置该计划的开始日期与结束日期,其中结束日期可以设置为无结束日期,也就是永远执行下去。
图14.16 【新建全文索引表计划】对话框
(4)设置完毕后单击【确定】按钮完成计划设计,返回如图14.17所示对话框。
图14.17 全文索引填充计划对话框
(5)在如图14.17所示对话框里,可以选择全文索引填充计划所要执行的填充方式,设置完毕后单击【确定】按钮完成操作。
注意:如果单击【确定】按钮之后出现如图14.18所示的失败对话框,请先安装SQL Server 2005 SP1(下载地址为:http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&
FamilyID=cb6c71ea-d649-47ff-9176-e7cac58fd4bc),然后再安装版本为9.0.2153的SQL Server 2005累积修补程序包(下载地址为:http://support.microsoft.com/kb/918222/zh-cn)。
图14.18 添加计划失败对话框
使用类似的方法也可以定时填充全文目录:
(1)右击全文目录名,在弹出的快捷菜单里选择【属性】选项。
(2)在弹出的如图14.4所示的【全文目录属性】对话框里选择【填充计划】选项。
(3)弹出与14-15所示的填充计划对话框,其添加计划的步骤与创建全文索引的填充计划几乎相同,在此就不再赘述了。
14.7 使用全文搜索查询
设置完全文索引并填充完毕之后,就可以通过全文搜索来查询数据了。使用全文搜索来查询数据所用到的T-SQL语句也是SELECT语句,只是在设置查询条件时和前面所说过的SELECT语句的查询条件设置有些不同。在T-SQL语言中,可以在SELECT语句的WHERE子句里设置全文搜索的查询条件,也可以在FROM子句里设置查询条件,此时将返回结果作为FROM子句中的表格来使用。
如果要在WHERE子句里设置全文搜索的查询条件,可以使用CONTAINS和FREETEXT两个谓词;如果要在FROM子句里设置全文搜索的查询条件 ,可以使用CONTAINSTABLE和FREETEXTTABLE两个行集值函数。
14.7.1 使用CONTAINS搜索
CONTAINS用于SELECT语句的WHERE子句中,可以支持使用复杂的语法在字符列中搜索词、子句、衍生字或位置相近的字符串。使用CONTAINS谓词可以在数据表中使用以下五种形式搜索数据:
l 简单词:也就是可以搜索一个或多个特定的词或短语。词可以包括一个或多个字符,中间没有空格或标点。短语可以是由空格分隔的多个词组成,但词之间可以有标点也可以没标点。
l 派生词:也就是可以搜索特定词的变形,一般是指英语中的单词,其有过去式、现在式、将来式等不同的形式。派生词是指可以包含该单词的所有其他形式。
l 前缀词:也就是可以搜索指定文本开头的词或短语。一般也用于英文单词中,可以指定一个英文单词的前几个字母来作为搜索条件。
l 加权词:也就是可以给多个搜索条件加上权值,加权值越高的记录排在越前面。
l 邻近词:也就是可以搜索与另一个词或短语相邻近的词或短语。
下面分别介绍如何使用这些不同的方式来搜索数据。
14.7.1.1 CONTAINS的语法
CONTAINS的语法代码如下:
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 ]
)
其中常用的参数为:
l column_name:字段名
l column_list:字段名列表
l *:所有字段
l LANGUAGE language_term:用于设置查询时所用的语言。例如在image字段里可能会存储了多种语言的文档,该参数允许用户指定搜索使用的语言,从而提高匹配率。
l INFLECTIONAL:用于指定使用与语言相关的词干分析器。词干分析器用于根据每种具体语言的判断词干。
l THESAURUS:用于指定同义词库。
14.7.1.2 简单词的搜索方式
简单词的搜索方式就是搜索一个或多个特定的词或短语。
例一、搜索文章表的标题中含有“上海”的记录,其代码如下:
SELECT * FROM 文章
WHERE CONTAINS(标题,'上海')
例二、搜索文章表的内容中含有“上海”或“广州”的记录,其代码如下:
SELECT * FROM 文章
WHERE CONTAINS(内容,' "上海" OR "广州"')
注意例二与例一的不同,在CONTAINS谓词的第二个参数里,将“”上海” OR “广州””做为一个字符串传递给CONTAINS。使用以下代码将会出错:
SELECT * FROM 文章
WHERE CONTAINS(内容,' 上海‘ OR ’广州')
14.7.1.3 派生词的搜索方式
派生词的搜索方式主要用在英文当中,因为英文单词中含有现在式、过去式、将来式、单复数等不同的形式,使派生词的搜索方式可以将字段中包括该单词的所有形式的记录都搜索出来。例如使用派生词方式搜索包含单词download的记录,则会把包含download、downloading等派生词的记录都搜索出来。
例三、搜索文章表中内容中含有download及其派生词的记录,其代码如下:
SELECT * FROM 文章
WHERE CONTAINS(内容,'FORMSOF(INFLECTIONAL,download)')
注意CONTAINS谓词的不同处,运行结果如图14.19所示。
图14.19 运行结果
在图14.19中可以看到只查询到一条记录,而并未将download的派生词也搜索进来,这是因为从一开始设置全文索引时,所采用的是数据库默认的断字符语言,即简体中文,而在中文中没有派生词,所以使用派生词方式搜索数据是起不到其作用的。此时可以通过修改全文索引的断字符语言来达到搜索效果。修改方式如下:
(1)右击全文索引所在的数据表,在弹出的快捷菜单中选择【全文索引】à【属性】弹出如图14.12所示【全文索引属性】对话框。
(2)在【全文索引属性】对话框里选择【列】选项,弹出如图14.20所示对话框,修改【内容】字段的【断字符语言】为“English”。
图14.20 修改断字符语言
(3)单击【确定】按钮完成操作。
再次运行例三中的代码,其运行结果如图14.21所示。
图14.21 正确的运行结果
14.7.1.4 前缀词的搜索方式
前缀词的搜索方式主要也是用在搜索英文中,例如搜索以“do”开头的单词,则可以将doctor、document、download等单词都搜索出来。
例四、搜索文章表中内容中含有“do”开头的单词的记录,其代码如下:
SELECT * FROM 文章
WHERE CONTAINS(内容,' "do*" ')
此方式有点类似与like子句的通配符方式,但只能使用“*”,并且只能放在英文字母之后,如“*do”、“*do*”都是错误的表达方式。
14.7.1.5 加权词的搜索方式
当以多个字符串作为搜索条件搜索记录时,可以为不同的字符串加上一个加权值,这个加权值是介于0和1之间的数值,加权值越高的记录排在越前面。
例五、搜索文章表中内容中含有“download”、“上海”、“山西”的记录,并为不同的条件加上加权值,其代码如下:
SELECT * FROM 文章
WHERE CONTAINS(内容,
'ISABOUT ("download" weight(0.9),
"上海" weight(0.6),
"山西" weight(0.5))')
或
SELECT * FROM 文章
WHERE CONTAINS(内容,
'ISABOUT (download weight(0.9),
上海 weight(0.6),
山西 weight(0.5))')
事实上在该SELECT语句的返回结果集里,并没有按加权值的大小来排序,因为WEIGHT不影响CONTAINS查询的结果,只会影响CONTAINSTABLE查询中的排序。
说明:使用本例时最好将“内容”字段的“断字符语言”改回简体中文,否则会影响中文的搜索结果。
14.7.1.6 邻近词的搜索方式
邻近词的搜索方式可以搜索记录中位置相近的两个字符,例如要搜索文章标题为“教育部拟取消教师资格终身制实行定期认证”的文章,完整的标题名记不清楚了,只记得“教育部”和“资格”,则可以以邻近词的搜索方式进行查询。
例六、搜索文章内容中与教育部表示相关的记录,其代码如下:
SELECT * FROM 文章
WHERE CONTAINS(内容,' "教育部" NEAR "表示"')
14.7.2 使用FREETEXT搜索
FREETEXT搜索方式与CONTAINS搜索方式相比,其搜索结果表现都十分不精确,因为FREETEXT的搜索方式是将一个句子中的每个单字拆分开进行搜索的。例如:如果使用CONTAINS搜索方式搜索条件为“教育部”的记录,那么搜索出来的将是记录里包含“教育部”三个字符串的记录。如果使用FREETEXT搜索方式搜索条件为“教育部”的记录,那么搜索出来的将是记录里包含“教”或“育”或“部”的记录。如果搜索的是英文字符串“SQL Server 2005”,则拆分为“SQL”、“Server”和“2005”来进行搜索,只要满足其中一个条件都算搜索成功。FREETEXT的语法代码为:
FREETEXT ( { column_name | (column_list) | * }
, 'freetext_string' [ , LANGUAGE language_term ] )
其中:
l column_name:为字段名。
l column_list:为字段列表。
l *:代码所有字段。
l 'freetext_string':搜索的字符串。
l LANGUAGE language_term:用于单词断字、词干分析、同义词库查询以及干扰词删除的特定的语言。
FREETEXT的搜索方式没有CONTAINS复杂,下面举例说明:
例七、用CONTAINS和FREETEXT两种方式来搜索“教育部”字符串,其代码如下:
SELECT * FROM 文章
WHERE FREETEXT(内容,'教育部')
SELECT * FROM 文章
WHERE CONTAINS (内容,'教育部')
其运行结果如图14.22所示,使用CONTAINS查询结果要比使用FREETEXT的查询结果记录数要多得多。
图14.22 CONTAINS和FREETEXT的查询结果
14.7.3 使用CONTAINSTABLE搜索
CONTAINSTABLE函数与CONTAINS谓词类似,其可以返回符合条件的多条记录,但是返回的记录是作为数据表出现在SELECT语句的FROM子句中。这个数据表里只包含两个字段:一个字段名为“KEY”,该字段显示的是全文索引的唯一索引键的内容,也就是图14.6所示界面中所创建的索引列;另一个字段名为“RANK”,该字段是排名值字段,其排名值是由系统依查询符合的程度自动生成的。CONTAINSTABLE的语法代码为:
CONTAINSTABLE ( table , { column_name | (column_list ) | * } , ' < contains_search_condition > '
[ , LANGUAGE language_term]
[ ,top_n_by_rank ]
)
< 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 ]
)
从以上代码可以看得出,CONTAINSTABLE与CONTAINS的搜索条件一样分为五类,其形式也几乎一样,只是增加了table和top_n_by_rank两个参数:
l table:全文索引所在的数据表名。
l top_n_by_rank:返回的记录数,相当于SELECT语句中的top n。
下面举几个例子说明CONTAINSTABLE与CONTAINS在用法上不同的地方。
例八、查看文章表中内容含有“教育部”的记录的编号,其代码如下:
SELECT * FROM
CONTAINSTABLE(文章,内容,'教育部') as table1
在本例中可以看到,CONTAINSTABLE返回的结果是作为数据表的形式出现在FROM子句中。其运行结果如图14.23所示,查询的结果也就是CONTAINSTABLE返回的数据表的结果,只有两个字段。
图14.23 例八的运行结果
例九、查看文章表中内容含有“教育部”和“表示”的前十条记录,并按查询符合程度排序,其代码如下:
SELECT * FROM 文章 JOIN
CONTAINSTABLE(文章,内容,' "教育部" NEAR "表示" ',10) as table1
ON 文章.编号= table1.[KEY]
ORDER BY table1.RANK DESC
其运行结果如图14.24所示,在本例中,将CONTAINSTABLE函数返回的数据表与文章表JOIN起来进行联合查询,就好像一个真实的数据表一样。由于KEY是关键字,所以在本例当中用方括号将KEY括起来。
图14.24 例九的运行结果
例十、搜索文章表中内容中含有“download”、“上海”、“山西”的记录,并为不同的条件加上加权值,然后按权值排序。其代码如下:
SELECT * FROM 文章 JOIN
CONTAINSTABLE(文章,内容,
'ISABOUT ("download" weight(0.9),
"上海" weight(0.6),
"山西" weight(0.1))') AS TABLE1
ON 文章.编号 = TABLE1.[KEY]
ORDER BY TABLE1.RANK DESC
其运行结果如图14.25所示,RANK字段是依符合程度生成的数据再加上权值后的结果。
图14.25 例十的运行结果
14.7.4 使用FREETEXTTABLE搜索
与CONTAINSTABLE一样,FREETEXTTABLE函数也是返回拥有KEY和RANK两个字段的表,该表可以和数据库中的数据表一样使用。FREETEXTTABLE的语法代码如下所示:
FREETEXTTABLE (table , { column_name | (column_list) | * }
, 'freetext_string'
[ ,LANGUAGE language_term ]
[ ,top_n_by_rank ] )
由以上代码可以看出FREETEXTTABLE函数与FREETEXT谓词的语法代码相似,只是多了table和top_n_by_rank两个参数。
例十一、查看文章表中“内容”字段含有“教育部”的前十条记录,其代码如下:
SELECT 文章.内容,TABLE1.* FROM 文章JOIN
FREETEXTTABLE(文章,内容,'教育部',8) AS TABLE1
ON 文章.编号= TABLE1.[KEY]
运行结果如图14.26所示:
图14.26 例十一的运行结果
14.7.5 搜索image字段
在SQL Server 2005的image类型的字段里,不仅仅是可以存储图形文件,还可以存储如可执行文件、音乐文件、文本文件等众多文件类型。SQL Server 2005支持对存储在image类型的字段里的一些文件的内容进行全文搜索,但在创建全文索引时必须指明存储在image字段里的文件的类型。如图14.7所示。
SQL Server 2005支持对存储在image中的纯文本文件、网页文件、Word文件、Excel文件和PowerPoint文件的内容进行查询,其扩展名字段必须分别为txt、htm、doc、xls和ppt。全文索引创建完毕后,对image字段里的文件内容进行查询的方法与其他字段的查询方法是一样的:
例十二、查询存储在文章表的文件字段里的内容包含“数据库”的文件,其代码如下:
SELECT 编号,标题,文件,扩展名 FROM 文章
WHERE CONTAINS(文件,'数据库')
14.8 2005新增:与全文索引相关的T-SQL语句
在SQL Server 2005以前的版本中,创建与管理全文目录、全文索引主要是使用存储过程来完成。从SQL Server 2005开始新增加了一些与全文索引相关的T-SQL语句,可以用来创建与管理全文目录和全文索引。
14.8.1 创建全文目录
创建全文目录的T-SQL语句为:
CREATE FULLTEXT CATALOG catalog_name
[ON FILEGROUP filegroup ]
[IN PATH 'rootpath']
[WITH <catalog_option>]
[AS DEFAULT]
[AUTHORIZATION owner_name ]
<catalog_option>::=
ACCENT_SENSITIVITY = {ON|OFF}
其中参数说明如下:
l catalog_name:全文目录名称。
l ON FILEGROUP filegroup:包含全文目录的文件组名。
l IN PATH 'rootpath':全文目录的路径。
l AS DEFAULT:指定该全文目录为默认目录。
l AUTHORIZATION owner_name:将全文目录的所有者设为数据库用户名或角色的名称。
l ACCENT_SENSITIVITY:设置该全文目录的全文索引是否区分重音。
例十三、在Northwind数据库中创建一个名为“TSQL全文目录”全文目录,其代码如下:
CREATE FULLTEXT CATALOG TSQL全文目录
ON FILEGROUP [PRIMARY]
IN PATH 'E:"book"SQL Server 2005大全"数据库"第十四章"运行后数据库'
AS DEFAULT
14.8.2 更改全文目录属性
创建完全文目录之后,如果发现其设置有不如意之处,可以用T-SQL语句对其进行修改。更改全文目录属性的T-SQL语句代码如下:
ALTER FULLTEXT CATALOG catalog_name
{ REBUILD [ WITH ACCENT_SENSITIVITY = { ON | OFF } ]
| REORGANIZE
| AS DEFAULT
}
其中参数说明如下:
l catalog_name:全文目录名称
l REBUILD:重新生成全文目录。
l WITH ACCENT_SENSITIVITY:设置该全文目录的全文索引是否区分重音。
l REORGANIZE:执行主合并索引以便将在索引过程中创建的各个较小的索引合并成一个大索引。
l AS DEFAULT:指定该全文目录为默认目录。
例十四、重新生成“TSQL全文目录”,其代码如下:
ALTER FULLTEXT CATALOG TSQL全文目录
REBUILD
14.8.3 创建全文索引
有了全文目录后,可以在全文目录里创建全文索引。一个全文目录里可以包含多个全文索引,但一个全文索引只能属于一个全文目录。每个数据表只能有一个全文索引。创建全文索引的T-SQL语句代码如下:
CREATE FULLTEXT INDEX ON table_name
[(column_name [TYPE COLUMN type_column_name]
[LANGUAGE language_term] [,...n])]
KEY INDEX index_name
[ON fulltext_catalog_name]
[WITH
{CHANGE_TRACKING {MANUAL | AUTO | OFF [, NO POPULATION]}}
]
其中参数说明如下:
l table_name:数据表名。
l column_name:全文索引中包括的一列或多列的名称。只能对类型为char、varchar、nchar、nvarchar、text、ntext、image、xml和varbinary的列进行全文索引。
l TYPE COLUMN type_column_name:用于存储column_name的文档类型的数据表中的列名。
l LANGUAGE language_term:存储在column_name中的数据所用的语言。
l KEY INDEX index_name:数据表中唯一键索引的字段名。
l ON fulltext_catalog_name:全文目录名。
l MANUAL:指定是使用SQL Server代理还是手动传播跟踪日志。
l AUTO:当关联的数据表中修改了数据时,SQL Server自动更新全文索引。
l OFF[,NO POPULATION]:不保留对索引数据的更改列表。
例十五、为“文章”表的“标题”、“内容”和“文件”三个字段创建全文索引,其代码如下:
CREATE FULLTEXT INDEX
ON 文章(标题,内容,文件 TYPE COLUMN 扩展名)
KEY INDEX PK_文章
ON TSQL全文目录
注意:由于在前面的章节里已经为“文章”表创建了全文索引,因此在运行本例之前要先把原来创建的全文索引删除。
14.8.4 更改全文索引属性
创建完全文索引之后,如果发现其设置有不如意之处,可以用T-SQL语句对其进行修改。更改全文索引属性的T-SQL语句代码如下:
ALTER FULLTEXT INDEX ON table_name
{ ENABLE
| DISABLE
| SET CHANGE_TRACKING { MANUAL | AUTO | OFF }
| ADD ( column_name
[ TYPE COLUMN type_column_name ]
[ LANGUAGE language_term ] [,...n] )
[ WITH NO POPULATION ]
| DROP ( column_name [,...n] )
[WITH NO POPULATION ]
| START { FULL | INCREMENTAL | UPDATE } POPULATION
| STOP POPULATION
}
其中一些参数说明如下:
l table_name:数据表名。
l ENABLE | DISABLE:启用或禁用全文索引。
l MANUAL:指定是使用SQL Server代理还是手动传播跟踪日志。
l AUTO:当关联的数据表中修改了数据时,SQL Server自动更新全文索引。
l OFF:不保留对索引数据的更改列表。
l ADD:指定在全文索引中添加列。
l WITH NO POPULATION:指定添加过删除全文索引列之后不填充全文索引。
l DROP:指定在全文索引中删除列。
l START……POPULATION:开始填充全文索引。
l FULL:指定填充所有全文索引。
l INCREMENTAL:指定对上次填充以来修改过的行进行填充。
l UPDATE :指定对自上次更新更改跟踪索引以来的所有插入、更新或删除进行处理。
l STOP POPULATION:停止正在进行的填充。
例十六、禁用“文章”表的全文索引,其代码如下:
ALTER FULLTEXT INDEX ON 文章
DISABLE
例十七、启用“文章”表的全文索引,其代码如下:
ALTER FULLTEXT INDEX ON 文章
ENABLE
例十八、将“文章”表里的“文件”字段从全文索引里删除,其代码如下:
ALTER FULLTEXT INDEX ON 文章
DROP (文件)
例十九、填充“文章”表的全文索引,其代码如下:
ALTER FULLTEXT INDEX ON 文章
START FULL POPULATION
14.8.5 删除全文索引
删除全文索引的T-SQL的语法代码比较简单,如下所示:
DROP FULLTEXT INDEX ON table_name
例二十、删除“文章”表里的全文索引,其代码如下:
DROP FULLTEXT INDEX ON 文章
14.8.6 删除全文目录
删除全文目录的T-SQL的语法代码比较简单,如下所示:
DROP FULLTEXT CATALOG catalog_name
例二十一、删除“文章”表里的全文索引,其代码如下:
DROP FULLTEXT CATALOG TSQL全文目录
注意:要删除全文目录必须为空,即不能包含有全文索引。
14.9 小结
使用全文搜索可以快速、灵活地为存储在数据库中的文本数据的基于关键字的查询创建索引。与仅适用于字符模式的LIKE谓词不同,全文查询将根据特定语言的规则对词和短语进行操作,从而针对此数据执行语言搜索。
全文索引是由SQL Server FullText Search服务来维护的,必须选启动该服务才能使用全文索引。填充全文索引有三种方式:完全填充、增量填充和更改跟踪。
在全文索引中概念与术语比较多,如全文索引、全文目录、断字符、词干分析器、标记、筛选器、填充、干扰词等。了解怎么创建全文目录,怎么创建全文索引,怎么进行全文索引的填充,怎么使用调度让全文索引自动填充。
使用CONTAINS、FREETEXT两个谓词和CONTAINSTABLE、FREETEXTTABLE两个行集值函数可以用来进行全文搜索,其中CONTAINS和FREETEXT用在WHERE子句中,CONTAINSTABLE和FREETEXTTABLE用在FROM子句中。CONTAINS搜索有简单词、派生词、前缀词、加权词和邻近词五种搜索方式。FREETEXT只有一种搜索方式,但是其将一个句子中的每个单字拆分开进行搜索。
SQL Server 2005可以对存储在image类型字段里的文件进行全文搜索。其搜索的前提是必须要有一个字段指明image类型字段里存储的文件是什么类型。当为image类型字段设置好全文索引后,可以像其他字段一样地进行全文搜索。