华为云用户手册

  • 操作步骤 创建Simple词典。 1 2 3 4 CREATE TEXT SEARCH DICTIONARY public.simple_dict ( TEMPLATE = pg_catalog.simple, STOPWORDS = english ); 其中,停用词表文件全名为english.stop。关于创建simple词典的语法和更多参数,请参见CREATE TEXT SEARCH DICTIONARY。 使用Simple词典。 1 2 3 4 5 6 7 8 9 10 11 SELECT ts_lexize('public.simple_dict','Yes'); ts_lexize ----------- {yes} (1 row) SELECT ts_lexize('public.simple_dict','The'); ts_lexize ----------- {} (1 row) 设置参数ACCEPT=false,使Simple词典返回NULL,而不是返回非停用词的小写形式。 1 2 3 4 5 6 7 8 9 10 11 12 ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false ); SELECT ts_lexize('public.simple_dict','Yes'); ts_lexize ----------- (1 row) SELECT ts_lexize('public.simple_dict','The'); ts_lexize ----------- {} (1 row)
  • 停用词 停用词是很常见的词,几乎出现在每一个文档中,并且没有区分值。因此,在全文搜索的语境下可忽视它们。停用词处理逻辑和词典类型相关。其中,Ispell词典会先对标记进行规范化,然后再查看停用词表,而Snowball词典会最先检查输入标记是否为停用词。 例如,每个英文文本包含像a和the的单词,因此没必要将它们存储在索引中。然而,停用词影响tsvector中的位置,同时位置也会影响相关度: 1 2 3 4 SELECT to_tsvector('english','in the list of stop words'); to_tsvector ---------------------------- 'list':3 'stop':5 'word':6 位置1、2、4是停用词,所以不显示。为包含和不包含停用词的文档计算出的排序是完全不同的: 1 2 3 4 5 6 7 8 9 SELECT ts_rank_cd (to_tsvector('english','in the list of stop words'), to_tsquery('list & stop')); ts_rank_cd ------------ .05 SELECT ts_rank_cd (to_tsvector('english','list stop words'), to_tsquery('list & stop')); ts_rank_cd ------------ .1 父主题: 词典
  • 词典概述 词典用于定义停用词(stop words),即全文检索时不搜索哪些词。 词典还可以用于对同一词的不同形式进行规范化,这样同一个词的不同派生形式都可以进行匹配。规范化后的词称为词位(lexeme)。 除了提高检索质量外,词的规范化和删除停用词可以减少文档tsvector格式的大小, 从而提高性能。词的规范化和删除停用词并不总是具有语言学意义,用户可以根据应用环境在词典定义文件中自定义规范化和删除规则。 一个词典是一个程序,接收标记(token)作为输入,并返回: 如果token在词典中已知,返回对应lexeme数组(注意,一个标记可能对应多个lexeme)。 一个lexeme。一个新token会代替输入token被传递给后继词典(当前词典可被称为过滤词典)。 如果token在词典中已知,但它是一个停用词,返回空数组。 如果词典不能识别输入的token,返回NULL。 GaussDB (DWS)提供了多种语言的预定义词典,同时提供了五种预定义的词典模板,分别是Simple,Synonym,Thesaurus,Ispell,和Snowball,可用于创建自定义参数的新词典。 在使用全文检索时,建议用户: 可以在文本搜索配置中定义一个解析器,以及一组用于处理该解析器的输出标记词典。对于解析器返回的每个标记类型,可以在配置中指定不同的词典列表进行处理。当解析器输出一种类型的标记后,在对应列表的每个词典中会查阅该标记,直到某个词典识别它。如果它被识别为一个停用词, 或者没有任何词典识别,该token将被丢弃,即不被索引或检索到。通常情况下,第一个返回非空结果的词典决定了最终结果,后继词典将不会继续处理。但是一个过滤类型的词典可以依据规则替换输入token,然后将替换后的token传递给后继词典进行处理。 配置词典列表的一般规则是,第一个位置放置一个应用范围最小的、最具体化定义的词典,其次是更一般化定义的词典, 最后是一个普适定义的词典,比如Snowball词干词典或Simple词典。在下面例子中,对于一个针对天文学的文本搜索配置astro_en,可以定义标记类型asciiword(ASCII词)对应的词典列表为:天文术语的Synonym同义词词典, Ispell英语词典和Snowball英语词干词典。 1 2 ALTER TEXT SEARCH CONFIGURATION astro_en ADD MAPPING FOR asciiword WITH astro_syn, english_ispell, english_stem; 过滤类型的词典可以放置在词典列表中除去末尾的任何地方,放置在末尾时是无效的。使用这些词典对标记进行部分规范化,可以有效简化后继词典的处理。 父主题: 词典
  • 处理tsquery GaussDB(DWS)提供了函数和操作符用来操作tsquery类型的查询。 tsquery && tsquery 返回两个给定查询tsquery的与结果。 tsquery || tsquery 返回两个给定查询tsquery的或结果。 !! tsquery 返回给定查询tsquery的非结果。 numnode(query tsquery) returns integer 返回tsquery中的节点数目(词素加操作符),这个函数在检查查询是否有效(返回值大于0),或者只包含停用词(返回值等于0)时,是有用的。例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 SELECT numnode(plainto_tsquery('the any')); NOTICE: text-search query contains only stop words or doesn't contain lexemes, ignored CONTEXT: referenced column: numnode numnode --------- 0 (1 row) SELECT numnode('foo & bar'::tsquery); numnode --------- 3 (1 row) querytree(query tsquery) returns text 返回可用于索引搜索的tsquery部分,该函数对于检测非索引查询是有用的(例如只包含停用词或否定项)。例如: 1 2 3 4 5 SELECT querytree(to_tsquery('!defined')); querytree ----------- T (1 row) 父主题: 附加功能
  • 处理tsvector GaussDB(DWS)提供了用来操作tsvector类型的函数和操作符。 tsvector || tsvector tsvector连接操作符返回一个新的tsvector类型,它综合了两个tsvector中词素和位置信息,并保留词素的位置信息和权重标签。右侧的tsvector的起始位置位于左侧tsvector的最后位置,因此,新生成的tsvector几乎等同于将两个原始文档字串连接后进行to_tsvector操作。(这个等价是不准确的,因为任何从左边tsvector中删除的停用词都不会影响结果,但是,在使用文本连接时,则会影响词素在右侧tsvector中的位置。) 相较于对文本进行连接后再执行to_tsvector操作,使用tsvector类型进行连接操作的优势在于可以对文档的不同部分使用不同配置进行解析。因为setweight函数会对给定的tsvector中的语素进行统一设置,如果想要对文档的不同部分设置不同的权重,需要在连接之前对文本进行解析和权重设置。 setweight(vector tsvector, weight "char") returns tsvector setweight返回一个输入tsvector的副本,其中每一个位置都使用给定的权重做了标记。权值可以为A、B、C或D(D是tsvector副本的默认权重,并且不在输出中呈现)。当对tsvector进行连接操作时,这些权重标签将会被保留,文档不同部分以不同的权重进行排序。 权重标签作用于位置,而不是词素。如果传入的tsvector已经被剥离了位置信息,那么setweight函数将什么都不做。 length(vector tsvector) returns integer 返回vector中的词素的数量。 strip(vector tsvector) returns tsvector 返回一个tsvector类型,其中包含输入的tsvector的同义词,但不包含任何位置和权重信息。虽然在相关性排序中,这里返回的tsvector要比未拆分的tsvector的作用小很多,但它通常都比未拆分的tsvector小的多。 父主题: 附加功能
  • 排序查询结果 排序是指试图针对特定查询衡量文档的相关度,从而将众多的匹配文档中相关度最高的文档排在最前。GaussDB(DWS)提供了两个预置的排序函数:ts_rank和ts_rank_cd。函数考虑了词法,距离,和结构信息;也就是,考虑查询词在文档中出现的频率、紧密程度、以及出现的地方在文档中的重要性。然而,相关性的概念是模糊的,并且是跟应用强相关的。不同的应用程序可能需要额外的信息来排序,比如,文档的修改时间,内置的排序函数等。也可以自定义排序函数或者采用附加因素组合这些排序函数的结果来满足特定需求。 两个预置的排序函数: 1 ts_rank([ weights float4[], ] vector tsvector, query tsquery [, normalization integer ]) returns float4 基于词素匹配率对vector进行排序: 1 ts_rank_cd([ weights float4[], ] vector tsvector, query tsquery [, normalization integer ]) returns float4 该函数需要位置信息的输入。因此它不能在"剥离"tsvector值的情况下运行—它将总是返回零。 对于这两个函数,可选的权重参数提供给词加权重的能力,词的权重大小取决于所加的权值。权重阵列指定在排序时为每类词汇加多大的权重。 {D-weight, C-weight, B-weight, A-weight} 如果没有提供权重,则使用缺省值:{0.1, 0.2, 0.4, 1.0} 通常的权重是用来标记文档特殊领域的词,如标题或最初的摘要,所以相对于文章主体中的词它们有着更高或更低的重要性。 由于较长的文档有更多的机会包含查询词,因此有必要考虑文档的大小。例如,包含有5个搜索词的一百字文档比包含有5个搜索词的一千字文档相关性更高。两个预置的排序函数都采用了一个整型的标准化选项来定义文档长度是否影响排序及如何影响。这个整型选项控制多个行为,所以它是一个屏蔽字:可以使用“|”指定一个或多个行为(例如,2|4)。 0(缺省)表示:跟长度大小没有关系 1 表示:排名(rank)除以(文档长度的对数+1) 2表示:排名除以文档的长度 4表示:排名除以两个扩展词间的调和平均距离。只能使用ts_rank_cd实现 8表示:排名除以文档中单独词的数量 16表示:排名除以单独词数量的对数+1 32表示:排名除以排名本身+1 当指定多个标志位时,会按照所列的顺序依次进行转换。 需要特别注意的是,排序函数不使用任何全局信息,所以不可能产生一个某些情况下需要的1%或100%的理想标准值。标准化选项32 (rank/(rank+1))可用于所有规模的从零到一之间的排序。而这只是一个表面变化,并不会影响搜索结果的排序。 下面是一个例子,仅选择排名前十的匹配: 由于SQL_ASCII的数据库编码格式不支持中文字符,请在Encoding为UTF8/GBK的数据库中执行以下示例: 1 2 3 4 5 6 7 8 9 10 11 12 SELECT id, title, ts_rank_cd(to_tsvector(body), query) AS rank FROM tsearch.pgweb, to_tsquery('science') query WHERE query @@ to_tsvector(body) ORDER BY rank DESC LIMIT 10; id | title | rank ----+------------------+------ 7 | Medical science | .2 3 | Computer science | .1 2 | Mathematics | .1 5 | Geography | .1 (4 rows) 这是使用标准化排序的相同例子: 1 2 3 4 5 6 7 8 9 10 11 12 SELECT id, title, ts_rank_cd(to_tsvector(body), query, 32 /* rank/(rank+1) */ ) AS rank FROM tsearch.pgweb, to_tsquery('science') query WHERE query @@ to_tsvector(body) ORDER BY rank DESC LIMIT 10; id | title | rank ----+------------------+---------- 7 | Medical science | .166667 3 | Computer science | .0909091 2 | Mathematics | .0909091 5 | Geography | .0909091 (4 rows) 下面是使用中文分词法排序查询的例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 CREATE TABLE tsearch.ts_zhparser(id int, body text); INSERT INTO tsearch.ts_zhparser VALUES(1, '排序'); INSERT INTO tsearch.ts_zhparser VALUES(2, '排序查询'); INSERT INTO tsearch.ts_zhparser VALUES(3, '查询排序'); --精确匹配 SELECT id, body, ts_rank_cd(to_tsvector('zhparser',body), query) AS rank FROM tsearch.ts_zhparser, to_tsquery('排序') query WHERE query @@ to_tsvector(body); id | body | rank ----+------+------ 1 | 排序 | .1 (1 row) --模糊匹配 SELECT id, body, ts_rank_cd(to_tsvector('zhparser',body), query) AS rank FROM tsearch.ts_zhparser, to_tsquery('排序') query WHERE query @@ to_tsvector('zhparser',body); id | body | rank ----+----------+------ 3 | 查询排序 | .1 1 | 排序 | .1 2 | 排序查询 | .1 (3 rows) 排序要遍历每个匹配的tsvector,因此资源消耗多,可能会因为I/O限制导致排序慢。可是这是很难避免的,因为实际查询中通常会有大量的匹配。 父主题: 控制文本搜索
  • plainto_tsquery plainto_tsquery将未格式化的文本querytext变换为tsquery。类似于to_tsvector,文本被解析并且标准化,然后在存在的词之间插入&(AND)布尔算子。 plainto_tsquery([ config regconfig, ] querytext text) returns tsquery 比如: 1 2 3 4 5 SELECT plainto_tsquery('english', 'The Fat Rats'); plainto_tsquery ----------------- 'fat' & 'rat' (1 row) 请注意,plainto_tsquery无法识别布尔运算符、权重标签,或在其输入中的前缀匹配标签: 1 2 3 4 5 SELECT plainto_tsquery('english', 'The Fat & Rats:C'); plainto_tsquery --------------------- 'fat' & 'rat' & 'c' (1 row) 在这里,所有输入的标点符号作为空格符号丢弃。
  • to_tsquery to_tsquery将查询转换为tsquery数据类型。 to_tsquery([ config regconfig, ] querytext text) returns tsquery to_tsquery从querytext中创建一个tsquery,querytext必须由布尔运算符& (AND)、| (OR)和! (NOT)分割的单个token组成。这些运算符可以用圆括弧分组。也就是说,to_tsquery输入必须遵循tsquery输入的通用规则,具体请参见文本搜索类型。不同的是基本tsquery以token表面值作为输入,而to_tsquery使用指定或默认分词器将每个token标准化成词素,并依据分词器丢弃属于停用词的token。例如: 1 2 3 4 5 SELECT to_tsquery('english', 'The & Fat & Rats'); to_tsquery --------------- 'fat' & 'rat' (1 row) 像在基本tsquery中的输入一样,权重可以附加到每个词素来限制它只匹配那些有相同weight(s)的tsvector词素。比如: 1 2 3 4 5 SELECT to_tsquery('english', 'Fat | Rats:AB'); to_tsquery ------------------ 'fat' | 'rat':AB (1 row) 同时,符号“*”也可以附加到词素来指定前缀匹配: 1 2 3 4 5 SELECT to_tsquery('supern:*A & star:A*B'); to_tsquery -------------------------- 'supern':*A & 'star':*AB (1 row) 这样的词素将匹配tsquery中指定字符串和权重的项。
  • 解析文档 GaussDB(DWS)中提供了to_tsvector函数把文档处理成tsvector数据类型。 1 to_tsvector([ config regconfig, ] document text) returns tsvector to_tsvector将文本文档解析为token,再将token简化到词素,并返回一个tsvector。其中tsvector中列出了词素及它们在文档中的位置。文档是根据指定的或默认的文本搜索分词器进行处理的。这里有一个简单的例子: 1 2 3 4 SELECT to_tsvector('english', 'a fat cat sat on a mat - it ate a fat rats'); to_tsvector ----------------------------------------------------- 'ate':9 'cat':3 'fat':2,11 'mat':7 'rat':12 'sat':4 通过以上例子可发现结果tsvector不包含词a、on或者it,rats变成rat,并且忽略标点符号-。 to_tsvector函数内部调用一个解析器,将文档的文本分解成token并给每个token指定一个类型。对于每个token,有一系列词典可供查询。词典系列因token类型的不同而不同。识别token的第一本词典将发出一个或多个标准词素来表示token。例如: rats变成rat因为词典认为词rats是rat的复数形式。 有些词被作为停用词(请参考停用词),这样它们就会被忽略,因为它们出现得太过频繁以致于搜索中没有用处。比如示例中的a、on和it。 如果没有词典识别token,那么它也被忽略。在上述示例中,符号“-”被忽略,因为词典没有给它分配token类型(空间符号),即空间符号永远不会被索引。 语法解析器、词典和要索引的token类型由选定的文本搜索分词器决定。可以在同一个数据库中有多种不同的分词器,以及提供各种语言的预定义分词器。在以上例子中,使用缺省分词器english。 函数setweight可以给tsvector的记录加权重,权重是字母A、B、C、D之一。这通常用于标记来自文档不同部分的记录,比如标题、正文。之后,这些信息可以用于排序搜索结果。 因为to_tsvector(NULL)会返回空,当字段可能是空的时候,建议使用coalesce。以下是为结构化文档创建tsvector的方法: 1 2 3 4 5 6 7 8 9 10 CREATE TABLE tsearch.tt (id int, title text, keyword text, abstract text, body text, ti tsvector); INSERT INTO tsearch.tt(id, title, keyword, abstract, body) VALUES (1, 'book', 'literature', 'Ancient poetry','Tang poem Song jambic verse'); UPDATE tsearch.tt SET ti = setweight(to_tsvector(coalesce(title,'')), 'A') || setweight(to_tsvector(coalesce(keyword,'')), 'B') || setweight(to_tsvector(coalesce(abstract,'')), 'C') || setweight(to_tsvector(coalesce(body,'')), 'D'); DROP TABLE tsearch.tt; 上例使用setweight标记已完成的tsvector中的每个词的来源,并且使用tsvector连接操作符“||”合并标记过的tsvector值,处理tsvector一节详细介绍了这些操作。 父主题: 控制文本搜索
  • 创建GIN索引 为了加速文本搜索,可以创建GIN索引。 1 CREATE INDEX pgweb_idx_1 ON tsearch.pgweb USING gin(to_tsvector('english', body)); to_tsvector()函数有两个版本,只输一个参数的版本和输两个参数的版本。 只输一个参数时,系统默认采用default_text_search_config所指定的分词器。 创建GIN索引时必须使用to_tsvector的两参数版本,否则索引内容可能不一致。只有指定了分词器名称的全文检索函数才可以在索引表达式中使用。因为索引的内容必须不受default_text_search_config的影响。由于default_text_search_config的值可以随时调整,从而导致不同条目生成的tsvector采用了不同的分词器,并且无法区分究竟使用了哪个分词器。正确地转储和恢复这样的索引也是不支持的。 在上述创建索引中to_tsvector使用了两个参数,只有当查询时也使用了两个参数,且参数值与索引中相同时,才会使用该索引。例如WHERE to_tsvector('english', body) @@ 'a & b' 可以使用索引,但WHERE to_tsvector(body) @@ 'a & b'不能使用索引。这可确保索引各条目是使用相同的分词器创建的。 索引中的分词器名称由另一列指定时可以建立更复杂的表达式索引。例如: 1 CREATE INDEX pgweb_idx_2 ON tsearch.pgweb USING gin(to_tsvector('zhparser', body)); 本示例中zhparser仅支持UTF8/GBK的数据库编码格式,在Encoding为SQL_ASCII下会报错。 其中body是pgweb表中的一列。当对索引的各条目使用了哪个分词器进行记录时,允许在同一索引中存在混合分词器。当文档集合中包含不同语言的文档时,这将是有用的。再次强调,打算使用索引的查询必须措辞匹配,例如,WHERE to_tsvector(config_name, body) @@ 'a & b'与索引中的to_tsvector措辞匹配。 索引甚至可以连接列: 1 CREATE INDEX pgweb_idx_3 ON tsearch.pgweb USING gin(to_tsvector('english', title || ' ' || body)); 另一个方法是创建一个单独的tsvector列控制to_tsvector的输出。下面的例子是title和body的连接, 当其它是NULL的时候,使用coalesce确保一个字段仍然会被索引: 1 2 ALTER TABLE tsearch.pgweb ADD COLUMN textsearchable_index_col tsvector; UPDATE tsearch.pgweb SET textsearchable_index_col = to_tsvector('english', coalesce(title,'') || ' ' || coalesce(body,'')); 然后为加速搜索创建一个GIN索引: 1 CREATE INDEX textsearch_idx_4 ON tsearch.pgweb USING gin(textsearchable_index_col); 现在,就可以执行一个快速全文搜索了: 1 2 3 4 5 6 7 8 9 10 SELECT title FROM tsearch.pgweb WHERE textsearchable_index_col @@ to_tsquery('science & Computer') ORDER BY last_mod_date DESC LIMIT 10; title -------- Computer science (1 rows) 相比于一个表达式索引,单独列方法的一个优势是:不必在查询时显式指定分词器以便能使用索引。正如上面例子所示,查询可以依赖于default_text_search_config。另一个优势是搜索比较快速,因为它没有必要重新利用to_tsvector调用来验证索引匹配。表达式索引方法更容易建立,且它需要较少的磁盘空间,因为tsvector形式没有明确存储。 父主题: 在数据库表中搜索文本
  • 搜索表 本章节主要介绍如何使用文本搜索运算符搜索数据库表。 一个简单查询:将body字段中包含science的每一行打印出来。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 DROP SCHEMA IF EXISTS tsearch CASCADE; CREATE SCHEMA tsearch; CREATE TABLE tsearch.pgweb(id int, body text, title text, last_mod_date date); INSERT INTO tsearch.pgweb VALUES(1, 'Philology is the study of words, especially the history and development of the words in a particular language or group of languages.', 'Philology', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(2, 'Mathematics is the science that deals with the logic of shape, quantity and arrangement.', 'Mathematics', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(3, 'Computer science is the study of processes that interact with data and that can be represented as data in the form of programs.', 'Computer science', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(4, 'Chemistry is the scientific discipline involved with elements and compounds composed of atoms, molecules and ions.', 'Chemistry', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(5, 'Geography is a field of science devoted to the study of the lands, features, inhabitants, and phenomena of the Earth and planets.', 'Geography', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(6, 'History is a subject studied in schools, colleges, and universities that deals with events that have happened in the past.', 'History', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(7, 'Medical science is the science of dealing with the maintenance of health and the prevention and treatment of disease.', 'Medical science', '2010-1-1'); INSERT INTO tsearch.pgweb VALUES(8, 'Physics is one of the most fundamental scientific disciplines, and its main goal is to understand how the universe behaves.', 'Physics', '2010-1-1'); SELECT id, body, title FROM tsearch.pgweb WHERE to_tsvector('english', body) @@ to_tsquery('english', 'science'); id | body | title ----+-------------------------------------------------------------------------------------------------------------------------+--------- 2 | Mathematics is the science that deals with the logic of shape, quantity and arrangement. | Mathematics 3 | Computer science is the study of processes that interact with data and that can be represented as data in the form of programs. | Computer science 5 | Geography is a field of science devoted to the study of the lands, features, inhabitants, and phenomena of the Earth and planets. | Geography 7 | Medical science is the science of dealing with the maintenance of health and the prevention and treatment of disease. | Medical science (4 rows) 像science这样的相关词都会被找到,因为这些词都被处理成了相同标准的词条。 上面的查询指定english配置来解析和规范化字符串。也可以省略此配置,通过default_text_search_config进行配置设置: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 SHOW default_text_search_config; default_text_search_config ---------------------------- pg_catalog.english (1 row) SELECT id, body, title FROM tsearch.pgweb WHERE to_tsvector(body) @@ to_tsquery('science'); id | body | title ----+-------------------------------------------------------------------------------------------------------------------------+--------- 2 | Mathematics is the science that deals with the logic of shape, quantity and arrangement. | Mathematics 3 | Computer science is the study of processes that interact with data and that can be represented as data in the form of programs. | Computer science 5 | Geography is a field of science devoted to the study of the lands, features, inhabitants, and phenomena of the Earth and planets. | Geography 7 | Medical science is the science of dealing with the maintenance of health and the prevention and treatment of disease. | Medical science (4 rows) 一个复杂查询:检索出在title或者body字段中包含treatment和science的最近10篇文档: 1 2 3 4 5 SELECT title FROM tsearch.pgweb WHERE to_tsvector(title || ' ' || body) @@ to_tsquery('treatment & science') ORDER BY last_mod_date DESC LIMIT 10; title -------- Medical science (1 rows) 为了清晰,举例中没有调用coalesce函数在两个字段中查找包含NULL的行。 以上例子均在没有索引的情况下进行查询。对于大多数应用程序来说,这个方法很慢。因此除了偶尔的特定搜索,文本搜索在实际使用中通常需要创建索引。 父主题: 在数据库表中搜索文本
  • 分词器 全文检索功能还可以做更多事情:忽略索引某个词(停用词),处理同义词和使用复杂解析,例如,不仅基于空格的解析。这些功能通过文本搜索分词器控制。GaussDB(DWS)支持多语言的预定义的分词器,并且可以创建分词器(gsql的\dF命令显示了所有可用分词器)。 在安装期间选择一个合适的分词器,并且在postgresql.conf中相应的设置default_text_search_config。如果为了整个集群使用同一个文本搜索分词器可以使用postgresql.conf中的值。如果需要在集群中使用不同分词器,可以使用ALTER DATABASE ... SET在任一数据库进行配置。用户也可以在每个会话中设置default_text_search_config。 每个依赖于分词器的文本搜索函数有一个可选的配置参数,用以明确声明所使用的分词器。仅当忽略这个参数的时候,才使用default_text_search_config。 为了更方便的建立自定义文本搜索分词器,可以通过简单的数据库对象建立分词器。 GaussDB(DWS)文本搜索功能提供了四种类型与分词器相关的数据库对象: 文本搜索解析器将文档分解为token,并且分类每个token(例如:词和数字)。 文本搜索词典将token转换成规范格式并且丢弃停用词。 文本搜索模板提供潜在的词典功能:一个词典指定一个模板,并且为模板设置参数。 文本搜索分词器选择一个解析器,并且使用一系列词典规范化语法分析器产生的token。 父主题: 介绍
  • 基本文本匹配 GaussDB(DWS)的全文检索基于匹配算子@@,当一个tsvector(document)匹配到一个tsquery(query)时,则返回true。其中,tsvector(document)和tsquery(query)两种数据类型可以任意排序。 1 2 3 4 5 SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector @@ 'cat & rat'::tsquery AS RESULT; result ---------- t (1 row) 1 2 3 4 5 SELECT 'fat & cow'::tsquery @@ 'a fat cat sat on a mat and ate a fat rat'::tsvector AS RESULT; result ---------- f (1 row) 正如上面例子表明,tsquery不仅是文本,且比tsvector包含的要多。tsquery包含已经标注化为词条的搜索词,同时可能是使用AND、OR、或NOT操作符连接的多个术语。详细请参见文本搜索类型。函数to_tsquery和plainto_tsquery对于将用户书写文本转换成适合的tsquery是非常有用的,比如将文本中的词标准化。类似地,to_tsvector用于解析和标准化文档字符串。因此,实际中文本搜索匹配看起来更像这样: 1 2 3 4 5 SELECT to_tsvector('fat cats ate fat rats') @@ to_tsquery('fat & rat') AS RESULT; result ---------- t (1 row) 需要注意的是,下面这种方式是不可行的: 1 2 3 4 5 SELECT 'fat cats ate fat rats'::tsvector @@ to_tsquery('fat & rat')AS RESULT; result ---------- f (1 row) 由于tsvector没有对rats进行标准化,所以rats不匹配rat。 @@操作符也支持text输入,允许一个文本字符串的显示转换为tsvector或者在简单情况下忽略tsquery。可用形式是: 1 2 3 4 tsvector @@ tsquery tsquery @@ tsvector text @@ tsquery text @@ text 形式text @@ tsquery等价于to_tsvector(text) @@ tsquery,而text @@ text等价于to_tsvector(text) @@ plainto_tsquery(text)。 父主题: 介绍
  • 文档概念 文档是全文搜索系统的搜索单元,例如:杂志上的一篇文章或电子邮件消息。文本搜索引擎必须能够解析文档,而且可以存储父文档的关联词素(关键词)。后续,这些关联词素用来搜索包含查询词的文档。 在GaussDB(DWS)中,文档通常是一个数据库表中的一行文本字段,或者这些字段的可能组合(级联)。文档可能存储在多个表中或者动态获取。换句话说,一个文档由被索引化的不同部分构成,可以不作为整体存储在任何地方。比如: 1 2 3 4 5 6 7 8 9 10 11 SELECT d_dow || '-' || d_dom || '-' || d_fy_week_seq AS identify_serials FROM tpcds.date_dim WHERE d_fy_week_seq = 1; identify_serials ------------------ 5-6-1 0-8-1 2-3-1 3-4-1 4-5-1 1-2-1 6-7-1 (7 rows) 实际上,在这些示例查询中,应该使用coalesce防止一个独立的NULL属性导致整个文档的NULL结果。 另外一种可能是:文档在文件系统中作为简单的文本文件存储。在这种情况下,数据库可以用于存储全文索引并且执行搜索,同时可以使用一些唯一标识从文件系统中检索文档。然而,从数据库外部检索文件需要拥有系统管理员权限或者特殊函数支持。因此,还是将所有数据保存在数据库中比较方便。同时,将所有数据保存在数据库中可以方便地访问文档元数据以便于索引和显示。 为了实现文本搜索目的,必须将每个文档减少至预处理后的tsvector格式。搜索和相关性排序都是在tsvector形式的文档上执行的。原始文档只有在被选中要呈现给用户时才会被当检索。因此,常将tsvector说成文档,但是很显然其实它只是完整文档的一种紧凑表示。 父主题: 介绍
  • 全文检索概述 全文检索(或者说文本搜索)提供了查询可读性文档的能力,并且通过查询相关度将结果进行排序。搜索最常见的方式是:找到包含指定查询词的所有记录,并且按照查询顺序返回这些记录。 文本搜索操作符在数据库中已存在多年。GaussDB(DWS)为文本数据类型提供~、~*、LIKE和ILIKE操作符,但这些操作符缺乏现代信息系统所要求的许多必要属性,不过这一问题可以通过使用索引及词典进行解决。 实时数仓(单机部署)暂不支持全文检索功能。 文本检索缺乏信息系统所要求的必要属性: 没有语义支持,即使是英语也是如此。 要识别派生词并不是那么容易,即使正则表达式也不能满足要求。例如satisfies和satisfy,当使用正则表达式寻找satisfy时,并不会查询到包含satisfies的文档。用户可以使用OR搜索多种派生形式,但过程非常繁琐。并且有些词会有上千的派生词,容易出错。 没有对搜索结果的分类(排序)。当搜索出成千的文档时,查找效率很低。 由于没有索引的支持,每一次的搜索需要遍历所有的文档,整体搜索比较缓慢。 使用全文索引可以对文档进行预处理,并且可以使后续的搜索更快速。预处理过程包括: 将文档解析成token。 为每个文档标记不同类别的token是非常有必要的,例如:数字、文字、复合词、电子邮件地址,这样就可以针对不同类别做不同的处理。原则上token的类别依赖于具体的应用,但对于大多数的应用来说,可以使用一组预定义的token类。 将token转换为词素。 词素像token一样是一个字符串,但它已经标准化处理,这样同一个词的不同形式是一样的。例如,标准化通常包括:将大写字母折成小写字母、删除后缀(如英语中的s或者es)。这将允许通过搜索找到同一个词的不同形式,不需要繁琐地输入所有可能的变形样式。同时,这一步通常会删除停用词。这些停用词通常因为太常见而对搜索无用。(总之,token是文档文本的原片段,而词素被认为是有用的索引和搜索词。)GaussDB(DWS)使用词典执行这一步,且提供了各种标准的词典。 保存搜索优化后的预处理文档。 比如,每个文档可以呈现为标准化词素的有序组合。伴随词素,通常还需要存储词素位置信息以用于邻近排序。因此文档包含的查询词越密集其排序越高。 词典能够对token如何标准化做到细粒度控制。使用合适的词典,可以定义不被索引的停用词。 数据类型tsvector用于存储预处理文档,tsquery用于存储查询条件,详细内容可参见文本搜索类型。为数据类型tsvector提供的函数和操作符可参见文本检索函数和操作符,其中最重要的是匹配运算符@@,请参见基本文本匹配。 父主题: 介绍
  • UNION,CASE和相关构造解析 如果所有输入都是相同的数据类型,不包括unknown类型(即输入的字符串文本未声明类型,该文本首先被定义成一个未知类型),那么解析成所输入的相同数据类型。 如果所有输入都是unknown类型则解析成text类型(字符串类型范畴的首选类型)。否则,忽略unknown输入。 如果输入不属于同一个类型范畴,查询失败(unknown类型除外)。 如果输入类型是同一个类型范畴,则选择该类型范畴的首选类型。(例外:union操作会选择第一个分支的类型作为所选类型。) 系统表pg_type中typcategory表示数据类型范畴, typispreferred表示是否是typcategory分类中的首选类型。 把所有输入转换为所选的类型(对于字符串保持原有长度)。如果从给定的输入到所选的类型没有隐式转换则失败。 若输入中含json、txid_snapshot、sys_refcursor或几何类型,则不能进行union。
  • 对于CASE、COALESCE、IF和IFNULL,在TD兼容模式下的处理 如果所有输入都是相同的数据类型,不包括unknown类型,那么解析成所输入的相同数据类型。 如果所有输入都是unknown类型则解析成text类型。 如果输入字符串(包括unknown,unknown当text来处理)和数字类型,那么解析成字符串类型,如果是其他不同的类型范畴,则报错。 如果输入类型是同一个类型范畴,则选择该类型的优先级较高的类型。 把所有输入转换为所选的类型。如果从给定的输入到所选的类型没有隐式转换则失败。
  • 对于CASE、COALESCE、IF和IFNULL,在MySQL兼容模式下的处理 如果所有输入都是相同的类型,不包括unknown类型,那么解析成所输入的相同数据类型。 如果所有输入都是unknown类型则解析成text类型。 如果输入是unknown类型和某一非unknown类型,则解析成该非unknown类型。 如果存在多种非unknown类型,将enum类型当做text类型,再进行比较。 如果输入类型是同一个类型范畴,则选择该类型的优先级较高的类型。如果是不同的类型范畴,则解析成text类型。 把所有输入转换为所选的类型。如果从给定的输入到所选的类型没有隐式转换则失败。
  • 示例 character存储类型转换。对一个目标列定义为character(20)的语句,下面的语句显示存储值的长度正确: 1 2 3 4 5 6 7 8 9 10 11 12 13 CREATE TABLE x1 ( customer_sk integer, customer_id char(20), first_name char(6), last_name char(8) ) with (orientation = column,compression=middle) distribute by hash (last_name); INSERT INTO x1(customer_sk, customer_id, first_name) VALUES (3769, 'abcdef', 'Grace'); SELECT customer_id, octet_length(customer_id) FROM x1; 图1 存储值长度 两个unknown文本缺省解析成text,这样就允许||操作符解析成text连接。然后操作符的text结果转换成bpchar("空白填充的字符型", character类型内部名称)以匹配目标字段类型。不过,从text到bpchar的转换是二进制兼容的,这样的转换是隐含的并且实际上不做任何函数调用。最后,在系统表里找到长度转换函数bpchar(bpchar, integer, boolean) 并且应用于该操作符的结果和存储的字段长。这个类型相关的函数执行所需的长度检查和额外的空白填充。
  • 值存储数据类型解析 查找与目标字段准确的匹配。 试着将表达式直接转换成目标类型。如果已知这两种类型之间存在一个已登记的转换函数,那么直接调用该转换函数即可。如果表达式是一个未知类型文本,该文本字符串的内容将交给目标类型的输入转换过程。 检查目标类型是否有长度转换。长度转换是一个从某类型到自身的转换。如果在pg_cast表里面找到一个,那么在存储到目标字段之前先在表达式上应用。这样的转换函数总是接受一个额外的类型为integer的参数,它接收目标字段的atttypmod值(实际上是其声明长度,atttypmod的解释随不同的数据类型而不同),并且它可能接受一个boolean类型的第三个参数,表示转换是显式的还是隐式的。转换函数负责施加那些长度相关的语义,比如长度检查或者截断。
  • 示例 示例1:圆整函数参数类型解析。只有一个round函数有两个参数(第一个是numeric,第二个是integer)。所以下面的查询自动把第一个类型为integer的参数转换成numeric类型。 1 SELECT round(4, 4); 图1 round返回信息 实际上它被分析器转换成: 1 SELECT round(CAST (4 AS numeric), 4); 因为带小数点的数值常量初始时被赋予numeric类型,因此下面的查询将不需要类型转换,并且可能会略微高效一些: 1 SELECT round(4.0, 4); 示例2:子字符串函数类型解析。有好几个substr函数,其中一个接受text和integer类型。如果用一个未声明类型的字符串常量调用它,系统将选择接受string类型范畴的首选类型(也就是text类型)的候选函数。 1 SELECT substr('1234', 3); 图2 substr返回信息 如果该字符串声明为varchar类型,就像从表中取出来的数据一样,分析器将试着将其转换成text类型: 1 SELECT substr(varchar '1234', 3); 图3 substr返回信息 被分析器转换后实际上变成: 1 SELECT substr(CAST (varchar '1234' AS text), 3); 分析器从PG_CAST表中获取到text和varchar是二进制兼容的,即可传递给接受类型的函数而不需要做任何物理转换。因此,在这种情况下,实际上没有做任何类型转换。 而且,如果以integer为参数调用函数,分析器将试图将其转换成text类型: 1 SELECT substr(1234, 3); 图4 substr返回信息 被分析器转换后实际上变成: SELECT substr(CAST (1234 AS text), 3); 图5 substr返回信息
  • 函数类型解析 从系统表PG_PROC中选择所有可能被选到的函数。如果使用了一个不带模式修饰的函数名字,那么认为该函数是那些在当前搜索路径中的函数。如果给出一个带修饰的函数名,那么只考虑指定模式中的函数。 如果搜索路径中找到了多个不同参数类型的函数。将从中选择一个合适的函数。 查找和输入参数类型完全匹配的函数。如果找到一个,则用之。如果输入的实参类型都是unknown类型,则不会找到匹配的函数。 如果未找到完全匹配,请查看该函数是否为一个特殊的类型转换函数。 寻找最优匹配。 抛弃那些输入类型不匹配并且也不能隐式转换成匹配的候选函数。unknown文本在这种情况下可以转换成任何东西。如果只剩下一个候选项,则用之,否则继续下一步。 遍历所有候选函数,保留那些输入类型匹配最准确的。此时,域被看作和它们的基本类型相同。如果没有一个函数能准确匹配,则保留所有候选。如果只剩下一个候选项,则用之,否则继续下一步。 遍历所有候选函数,保留那些需要类型转换时接受首选类型位置最多的函数。如果没有接受首选类型的函数,则保留所有候选。如果只剩下一个候选项,则用之,否则继续下一步。 如果有任何输入参数是unknown类型,检查剩余的候选函数对应参数位置的类型范畴。在每一个能够接受字符串类型范畴的位置使用string类型(这种对字符串的偏爱是合适的,因为unknown文本确实像字符串)。另外,如果所有剩下的候选函数都接受相同的类型范畴,则选择该类型范畴,否则抛出一个错误(因为在没有更多线索的条件下无法作出正确的选择)。现在抛弃不接受选定的类型范畴的候选函数,然后,如果任意候选函数在那个范畴接受一个首选类型,则抛弃那些在该参数位置接受非首选类型的候选函数。如果没有一个候选符合这些测试则保留所有候选。如果只有一个候选函数符合,则使用它;否则,继续下一步。 如果同时有unknown和已知类型的参数,并且所有已知类型的参数有相同的类型,假设unknown参数也是这种类型,检查哪个候选函数可以在unknown参数位置接受这种类型。如果正好一个候选符合,那么使用它。否则,产生一个错误。
  • 操作符类型解析 从系统表PG_OPERATOR中选出要考虑的操作符。如果可以找到一个参数类型以及参数个数都一致的操作符,那么这个操作符就是最终使用的操作符。如果找到了多个备选的操作符,那么将从中选择一个最合适的。 寻找最优匹配。 丢弃输入类型不匹配以及无法隐式转换成匹配的候选操作符。unknown文本在这种情况下可以转换成任何类型。如果只剩下一个候选操作符,则使用,否则继续下一步。 查看所有候选操作符,并保留输入类型最匹配的操作符。此时,域被看作和其基本类型相同。如果没有完全匹配的操作符,则保留所有候选。如果只剩下一个候选操作符,则使用,否则继续下一步。 查看所有候选操作符,保留需要类型转换时接受(属于输入数据类型的类型范畴的)首选类型位置最多的操作符。如果没有接受首选类型的操作符,则保留所有候选。如果只剩下一个候选操作符,则使用,否则继续下一步。 如果有任何输入参数是unknown类型,请检查其余候选操作符对应参数位置的类型范畴。在每一个能够接受string类型范畴的位置使用string类型(这种偏向字符串的做法合理,因为unknown文本跟字符串相似)。另外,如果所有剩下的候选操作符都接受相同的类型范畴,则选择该类型范畴,否则会报错(因为在没有更多线索的条件下无法作出正确的选择)。现在丢弃不接受选定类型范畴的候选操作符。此外,如果有任意候选操作符接受该范畴中的首选类型,则丢弃该参数接受非首选类型的候选操作符。如果没有一个操作符能被保留,则保留所有候选。如果只剩下一个候选操作符,则使用,否则继续下一步。 如果同时有unknown和已知参数,并且所有已知参数都是相同的类型,那么假设unknown参数也属于该类型,并检查哪些候选操作符在unknown参数位置接受该类型。如果只有一个操作符符合,则使用。否则,报错。
  • TD兼容模式下,空串转换为数值类型的处理 TD数据库不同于Oracle,Oracle将空串当做NULL进行处理,TD在将空串转换为数值类型的时候,默认将空串转换为0进行处理,因此查询空串会查询到数值为0的数据。同样地,在TD兼容模式下,字符串转换数值的过程中,也会将空串默认转换为相应数值类型的0值进行处理。除此之外,' - '、' + '、' '这些字符串也都会在TD兼容模式下默认转换为0进行处理,但是小数点字符串' . '会报错。例如: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 CREATE TABLE t1(no int,col varchar); INSERT INTO t1 values(1,''); INSERT INTO t1 values(2,null); SELECT * FROM t1 WHERE col is null; no | col ----+----- 2 | (1 row) SELECT * FROM t1 WHERE col=''; no | col ----+----- 1 | (1 row) MySQL兼容模式下对空串转换为数值类型的处理和TD兼容模式相同。
  • 背景信息 在SQL语言中,每个数据都与一个决定其行为和用法的数据类型相关。GaussDB(DWS)提供一个可扩展的数据类型系统,该系统比其它SQL实现更具通用性和灵活性。因而,GaussDB(DWS)中大多数类型转换是由通用规则来管理的,这种做法允许使用混合类型的表达式。 GaussDB(DWS)扫描/分析器只将词法元素分解成五个基本种类:整数、浮点数、字符串、标识符和关键字。大多数非数字类型首先表现为字符串。SQL语言的定义允许将常量字符串声明为具体的类型。例如: 1 2 3 4 5 SELECT text 'Origin' AS "label", point '(0,0)' AS "value"; label | value --------+------- Origin | (0,0) (1 row) 示例中有两个文本常量,类型分别为text和point。如果没有为字符串文本声明类型,则该文本首先被定义成一个unknown类型。 在GaussDB(DWS)分析器里,有四种基本的SQL结构需要独立的类型转换规则: 函数调用 多数SQL类型系统是建筑在一套丰富的函数上的。函数调用可以有一个或多个参数。因为SQL允许函数重载,所以不能通过函数名直接找到要调用的函数,分析器必须根据函数提供的参数类型选择正确的函数。 操作符 SQL允许在表达式上使用前缀或后缀(单目)操作符,也允许表达式内部使用双目操作符(两个参数)。像函数一样,操作符也可以被重载,因此操作符的选择也和函数一样取决于参数类型。 值存储 INSERT和UPDATE语句将表达式结果存入表中。语句中的表达式类型必须和目标字段的类型一致或者可以转换为一致。 UNION,CASE和相关构造 因为联合SELECT语句中的所有查询结果必须在一列里显示出来,所以每个SELECT子句中的元素类型必须相互匹配并转换成一个统一类型。类似地,一个CASE构造的结果表达式必须转换成统一的类型,这样整个case表达式会有一个统一的输出类型。同样的要求也存在于ARRAY构造以及GREATEST和LEAST函数中。 系统表PG_CAST存储了有关数据类型之间的转换关系以及如何执行这些转换的信息。 语义分析阶段会决定表达式的返回值类型并选择适当的转换行为。数据类型的基本类型分类,包括:boolean、numeric、string、bitstring、datetime、timespan、geometric和network。每种类型都有一种或多种首选类型用于解决类型选择的问题。根据首选类型和可用的隐含转换,就可能保证有歧义的表达式(那些有多个候选解析方案的)得到有效的方式解决。 所有类型转换规则需遵循以下基本原则: 隐含转换不能有奇怪的或不可预见的输出。 如果一个查询不需要隐含的类型转换,分析器和执行器不应该进行更多的额外操作。即任何一个类型匹配、格式清晰的查询不应该在分析器里耗费更多的时间,也不应该向查询中引入任何不必要的隐含类型转换调用。 如果一个查询在调用某个函数时需要进行隐式转换,当用户定义了一个有正确参数的函数后,解释器应该选择使用新函数。
  • NOT IN expression NOT IN (value [, ...]) 右侧括号中的是一个表达式列表。左侧表达式的结果与表达式列表的内容进行比较。如果在列表中的内容没有符合左侧表达式结果的内容,则NOT IN的结果为true。如果有符合的内容,则NOT IN的结果为false。 示例如下: 1 2 3 4 5 SELECT 8000+500 NOT IN (10000, 9000) AS RESULT; result ---------- t (1 row) 如果查询语句返回结果为空,或者表达式列表不符合表达式的条件且右侧表达式列表返回结果至少一处为空,则NOT IN的返回结果为null,而不是false。这样的处理方式和SQL返回空值的布尔组合规则是一致的。 在所有情况下X NOT IN Y等价于NOT(X IN Y)。
  • IN expression IN (value [, ...]) 右侧括号中的是一个表达式列表。左侧表达式的结果与表达式列表的内容进行比较。如果列表中的内容符合左侧表达式的结果,则IN的结果为true。如果没有相符的结果,则IN的结果为false。 示例如下: 1 2 3 4 5 SELECT 8000+500 IN (10000, 9000) AS RESULT; result ---------- f (1 row)
  • 条件表达式 在执行SQL语句时,可通过条件表达式筛选出符合条件的数据。 条件表达式主要有以下几种: CASE CASE表达式是条件表达式,类似于其他编程语言中的CASE语句。 CASE表达式的语法图请参考图1。 图1 case::= CASE子句可以用于合法的表达式中。condition是一个返回BOOLEAN数据类型的表达式: 如果结果为真,CASE表达式的结果就是符合该条件所对应的result。 如果结果为假,则以相同方式处理随后的WHEN或ELSE子句。 如果各WHEN condition都不为真,表达式的结果就是在ELSE子句执行的result。如果省略了ELSE子句且没有匹配的条件,结果为NULL。 示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 CREATE TABLE tpcds.case_when_t1(CW_COL1 INT) DISTRIBUTE BY HASH (CW_COL1); INSERT INTO tpcds.case_when_t1 VALUES (1), (2), (3); SELECT * FROM tpcds.case_when_t1; cw_col1 --------- 3 1 2 (3 rows) SELECT CW_COL1, CASE WHEN CW_COL1=1 THEN 'one' WHEN CW_COL1=2 THEN 'two' ELSE 'other' END FROM tpcds.case_when_t1; cw_col1 | case ---------+------- 3 | other 1 | one 2 | two (3 rows) DROP TABLE tpcds.case_when_t1; DECODE DECODE的语法图请参见图2。 图2 decode::= 将表达式base_expr与后面的每个compare(n)进行比较,如果匹配返回相应的value(n)。如果没有发生匹配,则返回default。 示例请参见条件表达式函数。 1 2 3 4 5 SELECT DECODE('A','A',1,'B',2,0); case ------ 1 (1 row) COALESCE COALESCE的语法图请参见图3。 图3 coalesce::= COALESCE返回它的第一个非NULL的参数值。如果参数都为NULL,则返回NULL。它常用于在显示数据时用缺省值替换NULL。和CASE表达式一样,COALESCE只计算用来判断结果的参数,即在第一个非空参数右边的参数不会被计算。 示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 CREATE TABLE tpcds.c_tabl(description varchar(10), short_description varchar(10), last_value varchar(10)) DISTRIBUTE BY HASH (last_value); INSERT INTO tpcds.c_tabl VALUES('abc', 'efg', '123'); INSERT INTO tpcds.c_tabl VALUES(NULL, 'efg', '123'); INSERT INTO tpcds.c_tabl VALUES(NULL, NULL, '123'); SELECT description, short_description, last_value, COALESCE(description, short_description, last_value) FROM tpcds.c_tabl ORDER BY 1, 2, 3, 4; description | short_description | last_value | coalesce -------------+-------------------+------------+---------- abc | efg | 123 | abc | efg | 123 | efg | | 123 | 123 (3 rows) DROP TABLE tpcds.c_tabl; 如果description不为NULL,则返回description的值,否则计算下一个参数short_description;如果short_description不为NULL,则返回short_description的值,否则计算下一个参数last_value;如果last_value不为NULL,则返回last_value的值,否则返回(none)。 1 2 3 4 5 SELECT COALESCE(NULL,'Hello World'); coalesce --------------- Hello World (1 row) NULLIF NULLIF的语法图请参见图4。 图4 nullif::= 只有当value1和value2相等时,NULLIF才返回NULL。否则它返回value1。 示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 CREATE TABLE tpcds.null_if_t1 ( NI_VALUE1 VARCHAR(10), NI_VALUE2 VARCHAR(10) ) DISTRIBUTE BY HASH (NI_VALUE1); INSERT INTO tpcds.null_if_t1 VALUES('abc', 'abc'); INSERT INTO tpcds.null_if_t1 VALUES('abc', 'efg'); SELECT NI_VALUE1, NI_VALUE2, NULLIF(NI_VALUE1, NI_VALUE2) FROM tpcds.null_if_t1 ORDER BY 1, 2, 3; ni_value1 | ni_value2 | nullif -----------+-----------+-------- abc | abc | abc | efg | abc (2 rows) DROP TABLE tpcds.null_if_t1; 如果value1等于value2则返回NULL,否则返回value1。 1 2 3 4 5 SELECT NULLIF('Hello','Hello World'); nullif -------- Hello (1 row) GREATEST(最大值),LEAST(最小值) GREATEST的语法图请参见图5。 图5 greatest::= 从一个任意数字表达式的列表里选取最大的数值。 1 2 3 4 5 SELECT greatest(9000,155555,2.01); greatest ---------- 155555 (1 row) LEAST的语法图请参见图6。 图6 least::= 从一个任意数字表达式的列表里选取最小的数值。 以上的数字表达式必须都可以转换成一个普通的数据类型,该数据类型将是结果类型。 列表中的NULL值将被忽略。只有所有表达式的结果都是NULL的时候,结果才是NULL。 1 2 3 4 5 SELECT least(9000,2); least ------- 2 (1 row) 示例请参见条件表达式函数。 NVL NVL的语法图请参见图7。 图7 nvl::= 如果value1为NULL则返回value2,如果value1非NULL,则返回value1。 示例: 1 2 3 4 5 SELECT nvl(null,1); nvl ----- 1 (1 row) 1 2 3 4 5 SELECT nvl ('Hello World' ,1); nvl --------------- Hello World (1 row) IF IF的语法图请参见图8。 图8 if::= 当bool_expr为true时,返回expr1,否则返回expr2。 示例请参见条件表达式函数。 IFNULL IFNULL的语法图请参见图9。 图9 ifnull::= 当expr1不为NULL时,返回expr1,否则返回expr2。 示例请参见条件表达式函数。 父主题: 表达式
  • MALLOC_CONF 环境变量MALLOC_CONF用于控制监控模块是否开启,位于${BIGDATA_HOME}/mppdb/.mppdbgs_profile文件内,默认开启。需注意: 修改此环境变量变化,需要重启数据库。 如果在集群中启用了om_monitor,完成环境变量设置后,先重启om_monitor进程后,然后重启数据库,使得开关生效。 该环境变量可以设置在集群所有服务器中,也可以仅设置在需要开启模块的个别服务器中,对GaussDB进程而言,各进程是根据各自MALLOC_CONF环境变量,控制模块是否打开。 MALLOC_CONF开启和关闭命令: 开启监控模块: export MALLOC_CONF=prof:true 关闭监控模块: export MALLOC_CONF=prof:false
  • pg_get_triggerdef(oid, boolean) 描述:获取触发器的定义信息。 参数:待查触发器的OID及是否以pretty方式展示。 返回值类型:text 仅在创建trigger时指定WHEN条件的情况下,布尔类型参数才生效。 示例: 1 2 3 4 5 6 7 8 9 10 11 SELECT pg_get_triggerdef(oid,true) FROM pg_trigger; pg_get_triggerdef ---------------------------------------------------------------------------------------------------------------------- CREATE TRIGGER insert_trigger BEFORE INSERT ON test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE tri_insert_func() (1 row) SELECT pg_get_triggerdef(oid,false) FROM pg_trigger; pg_get_triggerdef ---------------------------------------------------------------------------------------------------------------------- CREATE TRIGGER insert_trigger BEFORE INSERT ON test_trigger_src_tbl FOR EACH ROW EXECUTE PROCEDURE tri_insert_func() (1 row)
共100000条