华为云用户手册

  • 注意事项 只有数据库所有者或者被授予了数据库DROP权限的用户有权限执行DROP DATABASE命令,系统管理员默认拥有此权限。 不能对系统默认安装的三个数据库(POSTGRES、TEMPLATE0和TEMPLATE1)执行删除操作,系统做了保护。如果想查看当前服务中有哪几个数据库,可以用gsql的\l命令查看。 如果有用户正在与要删除的数据库连接,则删除操作失败。如果要查看当前存在哪些数据库连接,可以通过视图dv_sessions查看。 不能在事务块中执行DROP DATABASE命令。 确定删除数据库前需要执行“CLEAN CONNECTION TO ALL FORCE FOR DATABASE XXXX;”命令,用于强制停止当前已有的用户连接及后台线程,防止因为有后台线程未完全退出而导致的删库失败问题。此处需要注意,强制停止后台线程可能导致当前数据库数据一致性问题,此命令仅在确定删库阶段执行。 如果执行DROP DATABASE失败,事务回滚,需要再次执行一次DROP DATABASE IF EXISTS。 DROP DATABASE一旦执行将无法撤销,请谨慎使用。
  • \copy命令 \copy命令格式以及说明参见表1。 表1 \copy元命令说明 语法 说明 \copy { table [ ( column_list ) ] | ( query ) } { from | to } { filename | stdin | stdout | pstdin | pstdout } [ with ] [ binary ] [ oids ] [ delimiter [ as ] 'character' ] [ useeof ] [ null [ as ] 'string' ] [ csv [ header ] [ quote [ as ] 'character' ] [ escape [ as ] 'character' ] [ force quote column_list | * ] [ force not null column_list ] ] 在任何gsql客户端登录数据库成功后,可以使用该命令进行数据的导入/导出。但是与SQL的COPY命令不同,该命令读取/写入的文件是本地文件,而非数据库服务器端文件;所以,要操作的文件的可访问性、权限等,都是受限于本地用户的权限。 说明: \COPY只适合小批量、格式良好的数据导入,不会对非法字符做预处理,也无容错能力,无法适用于含有异常数据的场景。导入数据应优先选择GDS或COPY。
  • 操作步骤 创建Simple词典。 1 2 3 4 openGauss=# 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 openGauss=# SELECT ts_lexize('public.simple_dict','YeS'); ts_lexize ----------- {yes} (1 row) openGauss=# 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 13 openGauss=# ALTER TEXT SEARCH DICTIONARY public.simple_dict ( Accept = false ); ALTER TEXT SEARCH DICTIONARY openGauss=# SELECT ts_lexize('public.simple_dict','YeS'); ts_lexize ----------- (1 row) openGauss=# SELECT ts_lexize('public.simple_dict','The'); ts_lexize ----------- {} (1 row)
  • 注意事项 大多数词典的功能依赖于词典定义文件,词典定义文件名仅支持小写字母、数字、下划线组合。 临时模式pg_temp下不允许创建词典。 词典定义文件的字符集编码必须为UTF-8格式。实际应用时,如果与数据库的字符编码格式不一致,在读入词典定义文件时会进行编码转换。 通常情况下,每个session仅读取词典定义文件一次,当且仅当在第一次使用该词典时。需要修改词典文件时,可通过ALTER TEXT SEARCH DICTIONARY命令进行词典定义文件的更新和重新加载。
  • 示例 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 --创建文本搜索配置。 openGauss=# CREATE TEXT SEARCH CONFIGURATION ngram2 (parser=ngram) WITH (gram_size = 2, grapsymbol_ignore = false); --创建文本搜索配置。 openGauss=# CREATE TEXT SEARCH CONFIGURATION ngram3 (copy=ngram2) WITH (gram_size = 2, grapsymbol_ignore = false); --添加类型映射。 openGauss=# ALTER TEXT SEARCH CONFIGURATION ngram2 ADD MAPPING FOR multisymbol WITH simple; --创建用户joe。 openGauss=# CREATE USER joe IDENTIFIED BY 'xxxxxxxxxxx'; --修改文本搜索配置的所有者。 openGauss=# ALTER TEXT SEARCH CONFIGURATION ngram2 OWNER TO joe; --修改文本搜索配置的schema。 openGauss=# ALTER TEXT SEARCH CONFIGURATION ngram2 SET SCHEMA joe; --重命名文本搜索配置。 openGauss=# ALTER TEXT SEARCH CONFIGURATION joe.ngram2 RENAME TO ngram_2; --删除类型映射。 openGauss=# ALTER TEXT SEARCH CONFIGURATION joe.ngram_2 DROP MAPPING IF EXISTS FOR multisymbol; --删除文本搜索配置。 openGauss=# DROP TEXT SEARCH CONFIGURATION joe.ngram_2; openGauss=# DROP TEXT SEARCH CONFIGURATION ngram3; --删除Schema及用户joe。 openGauss=# DROP SCHEMA IF EXISTS joe CASCADE; openGauss=# DROP ROLE IF EXISTS joe;
  • 参数说明 name 要创建的文本搜索配置的名称。该名称可以有模式修饰。 parser_name 用于该配置的文本搜索分析器的名称。 source_config 要复制的现有文本搜索配置的名称。 configuration_option 文本搜索配置的配置参数,主要是针对parser_name执行的解析器,或者source_config隐含的解析器而言的。 取值范围:目前共支持default、ngram两种类型的解析器,其中default类型的解析器没有对应的configuration_option,ngram类型解析器对应的configuration_option如表1所示。 表1 ngram类型解析器对应的配置参数 解析器 配置参数 参数描述 取值范围 ngram gram_size 分词长度。 正整数,1~4 默认值:2 punctuation_ignore 是否忽略标点符号。 true(默认值):忽略标点符号。 false:不忽略标点符号。 grapsymbol_ignore 是否忽略图形化字符。 true:忽略图形化字符。 false(默认值):不忽略图形化字符。
  • 注意事项 若仅声明分析器,那么新的文本搜索配置初始没有从符号类型到词典的映射, 因此会忽略所有的单词。后面必须调用ALTER TEXT SEARCH CONFIGURATION命令创建映射使配置生效。如果声明了COPY选项,那么会自动拷贝指定的文本搜索配置的解析器、映射、配置选项等信息。 若模式名称已给出,那么文本搜索配置会在声明的模式中创建。否则会在当前模式创建。 定义文本搜索配置的用户成为其所有者。 PARSER和COPY选项是互相排斥的,因为当一个现有配置被复制,其分析器配置也被复制了。 若仅声明分析器,那么新的文本搜索配置初始没有从符号类型到词典的映射, 因此会忽略所有的单词。
  • 示例 byteawithoutorderwithequalcolin、byteawithoutorderwithequalcolout等函数为数据库内核中数据类型byteawithoutorderwithequalcol指定的in、out、send、recv等读写格式转换函数,具体可参考bytea类型的byteain、byteaout等函数,但会对本地的cek进行验证,需要密文字段中有本地存在的cekoid才能执行成功。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 -- 例如存在加密表int_type,int_col2为其加密列 -- 使用非密态客户端连接数据库,查询加密列密文 openGauss=# select int_col2 from int_type; int_col2 ------------------------------------------------------------------------------------------------------------------------------------------------------ \x01c35301bf421c8edf38c34704bcc82838742917778ccb402a1b7452ad4a6ac7371acc0ac33100000035fe3424919854c86194f1aa5bb4e1ca656e8fc6d05324a1419b69f488bdc3c6 (1 row) -- 将加密列密文当做byteawithoutorderwithequalcolin入参,格式从cstring输入转码转化成内部byteawithoutorderwithequalcol形式 openGauss=# select byteawithoutorderwithequalcolin('\x01c35301bf421c8edf38c34704bcc82838742917778ccb402a1b7452ad4a6ac7371acc0ac33100000035fe3424919854c86194f1aa5bb4e1ca656e8fc6d05324a1419b69f488bdc3c6'); byteawithoutorderwithequalcolin ------------------------------------------------------------------------------------------------------------------------------------------------------ \x01c35301bf421c8edf38c34704bcc82838742917778ccb402a1b7452ad4a6ac7371acc0ac33100000035fe3424919854c86194f1aa5bb4e1ca656e8fc6d05324a1419b69f488bdc3c6 (1 row) 由于byteawithoutorderwithequalcolin等的实现会对cek进行查找,并且判断是否为正常加密后的数据类型。 因此如果用户输入数据的格式不是加密后的数据格式,并且在本地不存在对应cek的情况下,会返回错误。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 openGauss=# SELECT * FROM byteawithoutorderwithequalcolsend('\x907219912381298461289346129'::byteawithoutorderwithequalcol); ERROR: cek with OID 596711794 not found LINE 1: SELECT * FROM byteawithoutorderwithequalcolsend('\x907219912... ^ openGauss=# SELECT * FROM byteawithoutordercolout('\x90721901999999999999912381298461289346129'); ERROR: cek with OID 2566986098 not found LINE 1: SELECT * FROM byteawithoutordercolout('\x9072190199999999999... SELECT * FROM byteawithoutorderwithequalcolrecv('\x90721901999999999999912381298461289346129'::byteawithoutorderwithequalcol); ERROR: cek with OID 2566986098 not found ^ openGauss=# SELECT * FROM byteawithoutorderwithequalcolsend('\x90721901999999999999912381298461289346129'::byteawithoutorderwithequalcol); ERROR: cek with OID 2566986098 not found LINE 1: SELECT * FROM byteawithoutorderwithequalcolsend('\x907219019... ^
  • 解析文档 GaussDB中提供了to_tsvector函数把文档处理成tsvector数据类型。 1 to_tsvector([ config regconfig, ] document text) returns tsvector to_tsvector将文本文档解析为token,再将token简化到词素,并返回一个tsvector。其中tsvector中列出了词素及它们在文档中的位置。文档是根据指定的或默认的文本搜索分词器进行处理的。这里有一个简单的例子: 1 2 3 4 openGauss=# 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 openGauss=# CREATE TABLE tsearch.tt (id int, title text, keyword text, abstract text, body text, ti tsvector); openGauss=# INSERT INTO tsearch.tt(id, title, keyword, abstract, body) VALUES (1, 'China', 'Beijing', 'China','China, officially the People''s Republic of China (PRC), located in Asia, is the world''s most populous state.'); openGauss=# 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'); openGauss=# DROP TABLE tsearch.tt; 上例使用setweight标记已完成的tsvector中的每个词的来源,并且使用tsvector连接操作符||合并标记过的tsvector值,处理tsvector一节详细介绍了这些操作。 父主题: 控制文本搜索
  • 参数 表1 SQLFreeHandle参数 关键字 参数说明 HandleType SQLFreeHandle要释放的句柄类型。必须为下列值之一: SQL_HANDLE_ENV SQL_HANDLE_DBC SQL_HANDLE_STMT SQL_HANDLE_DESC 如果HandleType不是这些值之一,SQLFreeHandle返回SQL_INVALID_HANDLE。 Handle 要释放的句柄。
  • 语法格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [ WITH [ RECURSIVE ] with_query [, ...] ] UPDATE [/*+ plan_hint */] [ ONLY ] table_name [ * ] [ [ AS ] alias ] SET {column_name = { expression | DEFAULT } |( column_name [, ...] ) = {( { expression | DEFAULT } [, ...] ) |sub_query }}[, ...] [ FROM from_list] [ WHERE condition ] [ RETURNING {* | {output_expression [ [ AS ] output_name ]} [, ...] }]; where sub_query can be: SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] { * | {expression [ [ AS ] output_name ]} [, ...] } [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY grouping_element [, ...] ] [ HAVING condition [, ...] ] [ ORDER BY {expression [ [ ASC | DESC | USING operator ] | nlssort_expression_clause ] [ NULLS { FIRST | LAST } ]} [, ...] ] [ LIMIT { [offset,] count | ALL } ]
  • 注意事项 表的所有者、拥有表UPDATE权限的用户或拥有UPDATE ANY TABLE权限的用户,有权更新表中的数据,系统管理员默认拥有此权限。 对expression或condition条件里涉及到的任何表要有SELECT权限。 不允许对表的分布列(distribute column)进行修改。 对于列存表,暂时不支持RETURNING子句。 列存表不支持结果不确定的更新(non-deterministic update)。试图对列存表用多行数据更新一行时会报错。 列存表的更新操作,旧记录空间不会回收,需要执行VACUUM FULL table_name进行清理。 对于列存复制表,暂不支持UPDATE操作。
  • 示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 --创建表student1。 openGauss=# CREATE TABLE student1 ( stuno int, classno int ) DISTRIBUTE BY hash(stuno); --插入数据。 openGauss=# INSERT INTO student1 VALUES(1,1); openGauss=# INSERT INTO student1 VALUES(2,2); openGauss=# INSERT INTO student1 VALUES(3,3); --查看数据。 openGauss=# SELECT * FROM student1; --直接更新所有记录的值。 openGauss=# UPDATE student1 SET classno = classno*2; --查看数据。 openGauss=# SELECT * FROM student1; --删除表。 openGauss=# DROP TABLE student1;
  • 参数说明 WITH [ RECURSIVE ] with_query [, ...] 用于声明一个或多个可以在主查询中通过名称引用的子查询,相当于临时表。 如果声明了RECURSIVE,那么允许SELECT子查询通过名称引用它自己。 其中with_query的详细格式为:with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( {select | values | insert | update | delete} ) with_query_name指定子查询生成的结果集名称,在查询中可使用该名称访问子查询的结果集。 column_name指定子查询结果集中显示的列名。 每个子查询可以是SELECT,VALUES,INSERT,UPDATE或DELETE语句。 用户可以使用MATERIALIZED / NOT MATERIALIZED对CTE进行修饰。 如果声明为MATERIALIZED,WITH查询将被物化,生成一个子查询结果集的拷贝,在引用处直接查询该拷贝,因此WITH子查询无法和主干SELECT语句进行联合优化(如谓词下推、等价类传递等),对于此类场景可以使用NOT MATERIALIZED进行修饰,如果WITH查询语义上可以作为子查询内联执行,则可以进行上述优化。 如果用户没有显示声明物化属性则遵守以下规则:如果CTE只在所属SELECT主干中被引用一次,且语义上支持内联执行,则会被改写为子查询内联执行,否则以CTE Scan的方式物化执行。 plan_hint子句 以/*+ */的形式在UPDATE关键字后,用于对UPDATE对应的语句块生成的计划进行hint调优,详细用法请参见章节使用Plan Hint进行调优。每条语句中只有第一个/*+ plan_hint */注释块会作为hint生效,里面可以写多条hint。 table_name 要更新的表名,可以使用模式修饰。 取值范围:已存在的表名称。 alias 目标表的别名。 取值范围:字符串,符合标识符命名规范。 column_name 要修改的字段名。 支持使用目标表的别名加字段名来引用这个字段。例如: UPDATE foo AS f SET f.col_name = 'postgres'; 取值范围:已存在的字段名。 expression 赋给字段的值或表达式。 DEFAULT 用对应字段的缺省值填充该字段。 如果没有缺省值,则为NULL。 sub_query 子查询。 使用同一数据库里其他表的信息来更新一个表可以使用子查询的方法。其中SELECT子句具体介绍请参考SELECT。 在update单列时,支持使用order by子句与limit子句;而在update多列时,则不支持使用order by子句与limit子句。 from_list 一个表的表达式列表,允许在WHERE条件里使用其他表的字段。与在一个SELECT语句的FROM子句里声明表列表类似。 目标表不能出现在from_list里,除非在使用一个自连接(此时它必须以from_list的别名出现)。 condition 一个返回Boolean类型结果的表达式。只有这个表达式返回true的行才会被更新。不建议使用int等数值类型作为condition,因为int等数值类型可以隐式转换为bool值(非0值隐式转换为true,0转换为false),可能导致非预期的结果。 output_expression 在所有需要更新的行都被更新之后,UPDATE命令用于计算返回值的表达式。 取值范围:使用任何table以及FROM中列出的表的字段。*表示返回所有字段。 output_name 字段的返回名称。
  • 场景二:常规数据倾斜巡检 在库中表个数少于1W的场景,直接使用倾斜视图查询当前库内所有表的数据倾斜情况。 1 SELECT * FROM pgxc_get_table_skewness ORDER BY totalsize DESC; 在库中表个数非常多(至少大于1W)的场景,因PGXC_GET_TABLE_SKEWNESS涉及全库查并计算非常全面的倾斜字段,所以可能会花费比较长的时间(小时级),建议参考PGXC_GET_TABLE_SKEWNESS视图定义,直接使用table_distribution()函数自定义输出,减少输出列进行计算优化,例如: 1 2 3 4 5 6 SELECT schemaname,tablename,max(dnsize) AS maxsize, min(dnsize) AS minsize FROM pg_catalog.pg_class c INNER JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace INNER JOIN pg_catalog.table_distribution() s ON s.schemaname = n.nspname AND s.tablename = c.relname INNER JOIN pg_catalog.pgxc_class x ON c.oid = x.pcrelid AND x.pclocatortype = 'H' GROUP BY schemaname,tablename;
  • 场景一:磁盘满后快速定位存储倾斜的表 首先,通过pg_stat_get_last_data_changed_time(oid)函数查询出近期发生过数据变更的表,鉴于表的最后修改时间只在进行IUD操作的CN记录,要查询库内1天(间隔可在函数中调整)内被修改的所有表,可以使用如下封装函数: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 CREATE OR REPLACE FUNCTION get_last_changed_table(OUT schemaname text, OUT relname text) RETURNS setof record AS $$ DECLARE row_data record; row_name record; query_str text; query_str_nodes text; BEGIN query_str_nodes := 'SELECT node_name FROM pgxc_node where node_type = ''C'''; FOR row_name IN EXECUTE(query_str_nodes) LOOP query_str := 'EXECUTE DIRECT ON (' || row_name.node_name || ') ''SELECT b.nspname,a.relname FROM pg_class a INNER JOIN pg_namespace b on a.relnamespace = b.oid where pg_stat_get_last_data_changed_time(a.oid) BETWEEN current_timestamp - 1 AND current_timestamp;'''; FOR row_data IN EXECUTE(query_str) LOOP schemaname = row_data.nspname; relname = row_data.relname; return next; END LOOP; END LOOP; return; END; $$ LANGUAGE 'plpgsql'; 然后,通过table_distribution(schemaname text, tablename text)查询出表在各个DN占用的存储空间。 1 SELECT table_distribution(schemaname,relname) FROM get_last_changed_table();
  • 语法格式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ALTER NODE nodename WITH ( [ TYPE = nodetype,] [ HOST = hostname,] [ PORT = portnum,] [ HOST1 = 'hostname',] [ PORT1 = portnum,] [ HOSTPRIMARY [ = boolean ],] [ PRIMARY [ = boolean ],] [ PREFERRED [ = boolean ],] [ SCTP_PORT = portnum,] [ CONTROL_PORT = portnum,] [ SCTP_PORT1 = portnum,] [ CONTROL_PORT1 = portnum, ] [ NODEIS_CENTRAL [ = boolean ]] ); PORT选项指定的端口号为节点间内部通信绑定的端口号,不同于外部客户端连接节点的端口号,可通过pgxc_node表查询。
  • 注意事项 只有序列的所有者或者被授予了序列ALTER权限的用户才能执行ALTER SEQUENCE命令,系统管理员默认拥有该权限。但要修改序列的所有者,当前用户必须是该序列的所有者或者系统管理员,且该用户是新所有者角色的成员。 当前版本仅支持修改拥有者、归属列和最大值。若要修改其他参数,可以删除重建,并用Setval函数恢复当前值。 ALTER SEQUENCE MAXVALUE不支持在事务、函数和存储过程中使用。 修改序列的最大值后,会清空该序列在所有会话的cache。 ALTER SEQUENCE会阻塞nextval、setval、currval和lastval的调用、
  • 参数说明 name 将要修改的序列名称。 IF EXISTS 当序列不存在时使用该选项不会出现错误消息,仅有一个通知。 OWNED BY 将序列和一个表的指定字段进行关联。这样,在删除那个字段或其所在表的时候会自动删除已关联的序列。 如果序列已经和表有关联后,使用这个选项后新的关联关系会覆盖旧的关联。 关联的表和序列的所有者必须是同一个用户,并且在同一个模式中。 使用OWNED BY NONE将删除任何已经存在的关联。 new_owner 序列新所有者的用户名。用户要修改序列的所有者,必须是新角色的直接或者间接成员,并且那个角色必须有序列所在模式上的CREATE权限。
  • 示例 1 2 3 4 5 6 7 8 9 10 11 12 --创建一个名为serial的递增序列,从101开始。 openGauss=# CREATE SEQUENCE serial START 101; --创建一个表,定义默认值。 openGauss=# CREATE TABLE T1(C1 bigint default nextval('serial')); --将序列serial的归属列变为T1.C1。 openGauss=# ALTER SEQUENCE serial OWNED BY T1.C1; --删除序列 openGauss=# DROP SEQUENCE serial cascade; openGauss=# DROP TABLE T1;
  • 语法格式 修改序列归属列 1 2 3 ALTER SEQUENCE [ IF EXISTS ] name [MAXVALUE maxvalue | NO MAXVALUE | NOMAXVALUE] [ OWNED BY { table_name.column_name | NONE } ] ; 修改序列的拥有者 1 ALTER SEQUENCE [ IF EXISTS ] name OWNER TO new_owner;
  • 示例 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 --创建一个表tb_for_label openGauss=# CREATE TABLE tb_for_label(col1 text, col2 text, col3 text); --创建一个模式schema_for_label openGauss=# CREATE SCHEMA schema_for_label; --创建一个视图view_for_label openGauss=# CREATE VIEW view_for_label AS SELECT 1; --创建一个函数func_for_label openGauss=# CREATE FUNCTION func_for_label RETURNS TEXT AS $$ SELECT col1 FROM tb_for_label; $$ LANGUAGE SQL; --基于表创建资源标签 openGauss=# CREATE RESOURCE LABEL IF NOT EXISTS table_label add TABLE(public.tb_for_label); --基于列创建资源标签 openGauss=# CREATE RESOURCE LABEL IF NOT EXISTS column_label add COLUMN(public.tb_for_label.col1); --基于模式创建资源标签 openGauss=# CREATE RESOURCE LABEL IF NOT EXISTS schema_label add SCHEMA(schema_for_label); --基于视图创建资源标签 openGauss=# CREATE RESOURCE LABEL IF NOT EXISTS view_label add VIEW(view_for_label); --基于函数创建资源标签 openGauss=# CREATE RESOURCE LABEL IF NOT EXISTS func_label add FUNCTION(func_for_label);
  • 在结果集中定位 ResultSet对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next方法将光标移动到下一行;因为该方法在ResultSet对象没有下一行时返回false,所以可以在while循环中使用它来迭代结果集。但对于可滚动的结果集,JDBC驱动程序提供更多的定位方法,使ResultSet指向特定的行。定位方法如表2所示。 表2 在结果集中定位的方法 方法 描述 next() 把ResultSet向下移动一行。 previous() 把ResultSet向上移动一行。 beforeFirst() 把ResultSet定位到第一行之前。 afterLast() 把ResultSet定位到最后一行之后。 first() 把ResultSet定位到第一行。 last() 把ResultSet定位到最后一行。 absolute(int) 把ResultSet移动到参数指定的行数。 relative(int) 通过设置为1向前(设置为1,相当于next())或者向后(设置为-1,相当于previous())移动参数指定的行。
  • 获取结果集中光标的位置 对于可滚动的结果集,可能会调用定位方法来改变光标的位置。JDBC驱动程序提供了获取结果集中光标所处位置的方法。获取光标位置的方法如表3所示。 表3 获取结果集光标的位置 方法 描述 isFirst() 是否在一行。 isLast() 是否在最后一行。 isBeforeFirst() 是否在第一行之前。 isAfterLast() 是否在最后一行之后。 getRow() 获取当前在第几行。
  • 设置结果集类型 不同类型的结果集有各自的应用场景,应用程序需要根据实际情况选择相应的结果集类型。在执行SQL语句过程中,都需要先创建相应的语句对象,而部分创建语句对象的方法提供了设置结果集类型的功能。具体的参数设置如表1所示。涉及的Connection的方法如下: 1 2 3 4 5 6 7 8 //创建一个Statement对象,该对象将生成具有给定类型和并发性的ResultSet对象。 createStatement(int resultSetType, int resultSetConcurrency); //创建一个PreparedStatement对象,该对象将生成具有给定类型和并发性的ResultSet对象。 prepareStatement(String sql, int resultSetType, int resultSetConcurrency); //创建一个CallableStatement对象,该对象将生成具有给定类型和并发性的ResultSet对象。 prepareCall(String sql, int resultSetType, int resultSetConcurrency); 表1 结果集类型 参数 描述 resultSetType 表示结果集的类型,具体有三种类型: ResultSet.TYPE_FORWARD_ONLY:ResultSet只能向前移动。是缺省值。 ResultSet.TYPE_SCROLL_SENSITIVE:在修改后重新滚动到修改所在行,可以看到修改后的结果。 ResultSet.TYPE_SCROLL_INSENSITIVE:对可修改例程所做的编辑不进行显示。 说明: 结果集从数据库中读取了数据之后,即使类型是ResultSet.TYPE_SCROLL_SENSITIVE,也不会看到由其他事务在这之后引起的改变。调用ResultSet的refreshRow()方法,可进入数据库并从其中取得当前游标所指记录的最新数据。 resultSetConcurrency 表示结果集的并发,具体有两种类型: ResultSet.CONCUR_READ_ONLY:如果不从结果集中的数据建立一个新的更新语句,不能对结果集中的数据进行更新。 ResultSet.CONCUR_UPDATEABLE:可改变的结果集。对于可滚动的结果集,可对结果集进行适当的改变。
  • 获取结果集中的数据 ResultSet对象提供了丰富的方法,以获取结果集中的数据。获取数据常用的方法如表4所示,其他方法请参考JDK官方文档。 表4 ResultSet对象的常用方法 方法 描述 int getInt(int columnIndex) 按列标获取int型数据。 int getInt(String columnLabel) 按列名获取int型数据。 String getString(int columnIndex) 按列标获取String型数据。 String getString(String columnLabel) 按列名获取String型数据。 Date getDate(int columnIndex) 按列标获取Date型数据 Date getDate(String columnLabel) 按列名获取Date型数据。
  • 客户端配置 不同于基于gsql的程序,JDBC默认支持服务证书确认,如果用户使用一个由认证中心(CA,全球CA或区域CA)签发的证书,则java应用程序不需要做什么,因为java拥有大部分认证中心(CA,全球CA或区域CA)签发的证书的拷贝。如果用户使用的是自签的证书,则需要配置客户端程序,使其可用,此过程依赖于openssl工具以及java自带的keytool工具,配置步骤如下: 如果使用内置证书,以下步骤有效。 在客户端机器上,上传证书文件。 以普通用户登录客户端机器。 创建“/tmp/cacert”目录。 mkdir /tmp/cacert 将根证书文件以及客户端证书和私钥文件放入所创建的目录下。 将根证书导入到trustStore中。 openssl x509 -in cacert.pem -out cacert.crt.der -outform der 生成中间文件cacert.crt.der。 keytool -keystore mytruststore -alias cacert -import -file cacert.crt.der 请用户根据提示信息输入口令,此口令为truststorepassword,例如xxxxxxxxx,从而生成mytruststore。 cacert.pem为根证书。 cacert.crt.der为中间文件。 mytruststore为生成的密钥库名称,此名称以及别名,用户可以根据需要进行修改。 将客户端证书和私钥导入到keyStore中。 openssl pkcs12 -export -out client.pkcs12 -in client.crt -inkey client.key 请用户根据提示信息输入clientkey,例如xxxxxxxxx,从而生成client.pkcs12。 keytool -importkeystore -deststorepass xxxxxxxxxxx -destkeystore client.jks -srckeystore client.pkcs12 -srcstorepass xxxxxxxxx -srcstoretype PKCS12 -alias 1 -destkeypass xxxxxxxxx 此处deststorepass与destkeypass需保持一致,srcstorepass需与上条命令中的export password保持一致。生成client.jks。
  • 示例 注:示例1和示例2选择其一。 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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 public class SSL{ public static void main(String[] args) { Properties urlProps = new Properties(); String urls = "jdbc:postgresql://10.29.37.136:8000/postgres"; /** * ================== 示例1 使用NonValidatingFactory通道 */ urlProps.setProperty("sslfactory","org.postgresql.ssl.NonValidatingFactory"); urlProps.setProperty("user", "world"); urlProps.setProperty("password", "test@123"); urlProps.setProperty("ssl", "true"); /** * ================== 示例2 使用证书 */ urlProps.setProperty("sslcert", "client.crt"); urlProps.setProperty("sslkey", "client.key.pk8"); urlProps.setProperty("sslrootcert", "cacert.pem"); urlProps.setProperty("user", "world"); urlProps.setProperty("ssl", "true"); /* sslmode可配置为:require、verify-ca、verify-full,以下三个示例选择其一*/ /* ================== 示例2.1 设置sslmode为require,使用证书 */ urlProps.setProperty("sslmode", "require"); /* ================== 示例2.2 设置sslmode为verify-ca,使用证书 */ urlProps.setProperty("sslmode", "verify-ca"); /* ================== 示例2.3 设置sslmode为verify-full,使用证书(Linux下验证) */ urls = "jdbc:postgresql://world:8000/postgres"; urlProps.setProperty("sslmode", "verify-full"); try { Class.forName("org.postgresql.Driver").newInstance(); } catch (Exception e) { e.printStackTrace(); } try { Connection conn; conn = DriverManager.getConnection(urls,urlProps); conn.close(); } catch (Exception e) { e.printStackTrace(); } } } /** * 注:将客户端密钥转化为DER格式: * openssl pkcs8 -topk8 -outform DER -in client.key -out client.key.pk8 -nocrypt * openssl pkcs8 -topk8 -inform PEM -in client.key -outform DER -out client.key.der -v1 PBE-MD5-DES * openssl pkcs8 -topk8 -inform PEM -in client.key -outform DER -out client.key.der -v1 PBE-SHA1-3DES * 以上算法由于安全级别较低,不推荐使用。 * 如果客户需要采用更高级别的私钥加密算法,启用bouncycastle或者其他第三方私钥解密密码包后可以使用的私钥加密算法如下: * openssl pkcs8 -in client.key -topk8 -outform DER -out client.key.der -v2 AES128 * openssl pkcs8 -in client.key -topk8 -outform DER -out client.key.der -v2 aes-256-cbc -iter 1000000 * openssl pkcs8 -in client.key -topk8 -out client.key.der -outform Der -v2 aes-256-cbc -v2prf hmacWithSHA512 * 启用bouncycastle:使用jdbc的项目引入依赖:bcpkix-jdk15on.jar包,版本建议:1.65以上。 */
  • tsquery tsquery类型表示一个检索条件,存储用于检索的词汇,并且使用布尔操作符&(AND),|(OR)和!(NOT)来组合他们,括号用来强调操作符的分组。to_tsquery函数及plainto_tsquery函数会将单词转换为tsquery类型前进行规范化处理。tsquery类型支持的最大长度没有限制。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 openGauss=# SELECT 'fat & rat'::tsquery; tsquery --------------- 'fat' & 'rat' (1 row) openGauss=# SELECT 'fat & (rat | cat)'::tsquery; tsquery --------------------------- 'fat' & ( 'rat' | 'cat' ) (1 row) openGauss=# SELECT 'fat & rat & ! cat'::tsquery; tsquery ------------------------ 'fat' & 'rat' & !'cat' (1 row) 在没有括号的情况下,!(非)结合的最紧密,而&(和)结合的比|(或)紧密。 tsquery中的词汇可以用一个或多个权字母来标记,这些权字母限制这次词汇只能与带有匹配权的tsvector词汇进行匹配。 1 2 3 4 5 openGauss=# SELECT 'fat:ab & cat'::tsquery; tsquery ------------------ 'fat':AB & 'cat' (1 row) 同样,tsquery中的词汇可以用*标记来指定前缀匹配: 1 2 3 4 5 openGauss=# SELECT 'super:*'::tsquery; tsquery ----------- 'super':* (1 row) 这个查询可以匹配tsvector中以“super”开始的任意单词。 请注意,前缀首先被文本搜索分词器处理,这也就意味着下面的结果为真: 1 2 3 4 5 openGauss=# SELECT to_tsvector( 'postgraduate' ) @@ to_tsquery( 'postgres:*' ) AS RESULT; result ---------- t (1 row) 因为postgres经过处理后得到postgr: 1 2 3 4 5 openGauss=# SELECT to_tsquery('postgres:*'); to_tsquery ------------ 'postgr':* (1 row) 这样就匹配postgraduate了。 'Fat:ab & Cats'规范化转为tsquery类型结果如下: 1 2 3 4 5 openGauss=# SELECT to_tsquery('Fat:ab & Cats'); to_tsquery ------------------ 'fat':AB & 'cat' (1 row)
  • tsvector tsvector类型表示一个检索单元,通常是一个数据库表中一行的文本字段或者这些字段的组合,tsvector类型的值是一个标准词位的有序列表,标准词位就是把同一个词的变型体都标准化相同的,在输入的同时会自动排序和消除重复,支持的最大长度为2046字节。to_tsvector函数通常用于解析和标准化文档字符串。 tsvector的值是唯一分词的分类列表,把一句话的词格式化为不同的词条,在进行分词处理的时候tsvector会自动去掉分词中重复的词条,按照一定的顺序录入。如: 1 2 3 4 5 openGauss=# SELECT 'a fat cat sat on a mat and ate a fat rat'::tsvector; tsvector ---------------------------------------------------- 'a' 'and' 'ate' 'cat' 'fat' 'mat' 'on' 'rat' 'sat' (1 row) 从上面的例子可以看出,通过tsvector把一个字符串按照空格进行分词,分词的顺序是按照长短和字母排序的。但是如果词条中需要包含空格或标点符号,可以用引号标记: 1 2 3 4 5 openGauss=# SELECT $$the lexeme ' ' contains spaces$$::tsvector; tsvector ------------------------------------------- ' ' 'contains' 'lexeme' 'spaces' 'the' (1 row) 如果在词条中使用引号,可以使用双$$符号作为标记: 1 2 3 4 5 openGauss=# SELECT $$the lexeme 'Joe''s' contains a quote$$::tsvector; tsvector ------------------------------------------------ 'Joe''s' 'a' 'contains' 'lexeme' 'quote' 'the' (1 row) 词条位置常量也可以放到词汇中: 1 2 3 4 5 openGauss=# SELECT 'a:1 fat:2 cat:3 sat:4 on:5 a:6 mat:7 and:8 ate:9 a:10 fat:11 rat:12'::tsvector; tsvector ------------------------------------------------------------------------------- 'a':1,6,10 'and':8 'ate':9 'cat':3 'fat':2,11 'mat':7 'on':5 'rat':12 'sat':4 (1 row) 位置常量通常表示文档中源字的位置。位置信息可以用于进行排名。位置常量的范围是1到255,最大值默认是255。相同词的重复位会被忽略掉。 拥有位置的词汇甚至可以用一个权来标记,这个权可以是A,B,C或D。默认的是D,因此输出中不会出现: 1 2 3 4 5 openGauss=# SELECT 'a:1A fat:2B,4C cat:5D'::tsvector; tsvector ---------------------------- 'a':1A 'cat':5 'fat':2B,4C (1 row) 权可以用来反映文档结构,如:标记标题与主体文字的区别。全文检索排序函数可以为不同的权标记分配不同的优先级。 下面的示例是tsvector类型标准用法。如: 1 2 3 4 5 openGauss=# SELECT 'The Fat Rats'::tsvector; tsvector -------------------- 'Fat' 'Rats' 'The' (1 row) 但是对于英文全文检索应用来说,上面的单词会被认为非规范化的,所以需要通过to_tsvector函数对这些单词进行规范化处理: 1 2 3 4 5 openGauss=# SELECT to_tsvector('english', 'The Fat Rats'); to_tsvector ----------------- 'fat':2 'rat':3 (1 row)
共100000条