华为云用户手册

  • 嵌套赋值 给变量嵌套赋值的语法请参见图2。 图2 nested_assignment_value::= 对以上语法格式的解释如下:图2 variable_name:变量名。 col_name:列名。 subscript:下标,针对数组变量使用,可以是值或表达式,类型必须为int。 value:可以是值或表达式。值value的类型需要和变量variable_name的类型兼容才能正确赋值。 示例: 123456789 gaussdb=# CREATE TYPE o1 as (a int, b int);gaussdb=# DECLARE TYPE r1 is VARRAY(10) of o1; emp_id r1;BEGIN emp_id(1).a := 5;--赋值 emp_id(1).b := 5*7784;END;/
  • 语法 给变量赋值的语法请参见图1。 图1 assignment_value::= 对以上语法格式的解释如下: variable_name:变量名。 value:可以是值或表达式。值value的类型需要和变量variable_name的类型兼容才能正确赋值。 示例: 1234567 gaussdb=# DECLARE emp_id INTEGER := 7788;--赋值BEGIN emp_id := 5;--赋值 emp_id := 5*7784;END;/
  • 语法格式 SELECT select_expressions INTO [STRICT] target FROM ...SELECT INTO [STRICT] target expression [FROM ..] 通过基础 SQL 命令加INTO子句可以将单行或多列的结果赋值给一个变量(记录、行类型、标量变量列表)。 target参数可以是一个记录变量、一个行变量或一个有逗号分隔的简单变量和记录/行域列表。 STRICT选项 在开启参数set behavior_compat_options = 'select_into_return_null'的前提下(默认未开启),若指定该选项则该查询必须刚好返回一行不为空的结果集,否则会报错,报错信息可能是NO_DATA_FOUND(没有行)、TOO_MANY_ROWS(多于一行)或QUERY_RETURNED_NO_ROWS (没有数据返回)。若不指定该选项则没有该限定,且支持返回空结果集。
  • EXECUTE IMMEDIATE 语法图请参见图1。 图1 EXECUTE IMMEDIATE dynamic_select_clause::= using_clause子句的语法图参见图2。 图2 using_clause::= 对以上语法格式的解释如下: define_variable:用于指定存放单行查询结果的变量。 USING IN bind_argument:用于指定存放传递给动态SQL值的变量,即在dynamic_select_string中存在占位符时使用。 USING OUT bind_argument:用于指定存放动态SQL返回值的变量。 查询语句中,into和out不能同时存在; 占位符命名以“:”开始,后面可跟数字、字符或字符串,与USING子句的bind_argument一一对应; bind_argument只能是值、变量或表达式,不能是表名、列名、数据类型等数据库对象,即不支持使用bind_argument为动态SQL语句传递模式对象。如果存储过程需要通过声明参数传递数据库对象来构造动态SQL语句(常见于执行DDL语句时),建议采用连接运算符“||”拼接dynamic_select_clause; 动态PL/SQL块允许出现重复的占位符,即相同占位符只能与USING子句的一个bind_argument按位置对应。当设置guc参数behavior_compat_options值为dynamic_sql_compat时,会按照占位符的顺序依次匹配USING子句bind_argument,重复的占位符不会再识别为同一个占位符。
  • 语法 语法请参见图1。 图1 call_procedure::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: CALL procedure_name: 调用存储过程。 [:placeholder1,:placeholder2,…]: 存储过程参数占位符列表。占位符个数与参数个数相同。 USING [IN|OUT|IN OUT] bind_argument: 用于指定存放传递给存储过程参数值的变量。bind_argument前的修饰符与对应参数的修饰符一致。
  • 示例 1 2 3 4 5 6 7 8 9101112131415161718 --创建存储过程proc_staffsgaussdb=# CREATE OR REPLACE PROCEDURE proc_staffs(section NUMBER(6),salary_sum out NUMBER(8,2),staffs_count out INTEGER)ISBEGINSELECT sum(salary), count(*) INTO salary_sum, staffs_count FROM hr.staffs where section_id = section;END;/--调用存储过程proc_return.gaussdb=# CALL proc_staffs(2,8,6);--清除存储过程gaussdb=# DROP PROCEDURE proc_staffs;
  • 示例 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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 下面示例中用到的表定义如下:gaussdb=# \d emp_rec Table "public.emp_rec" Column | Type | Modifiers ----------+--------------------------------+----------- empno | numeric(4,0) | not null ename | character varying(10) | job | character varying(9) | mgr | numeric(4,0) | hiredate | timestamp(0) without time zone | sal | numeric(7,2) | comm | numeric(7,2) | deptno | numeric(2,0) | --演示在函数中对数组进行操作。gaussdb=# CREATE OR REPLACE FUNCTION regress_record(p_w VARCHAR2)RETURNSVARCHAR2 AS $$DECLARE --声明一个record类型. type rec_type is record (name varchar2(100), epno int); employer rec_type; --使用%type声明record类型 type rec_type1 is record (name emp_rec.ename%type, epno int not null :=10); employer1 rec_type1; --声明带有默认值的record类型 type rec_type2 is record ( name varchar2 not null := 'SCOTT', epno int not null :=10); employer2 rec_type2; CURSOR C1 IS select ename,empno from emp_rec order by 1 limit 1; BEGIN --对一个record类型的变量的成员赋值。 employer.name := 'WARD'; employer.epno = 18; raise info 'employer name: % , epno:%', employer.name, employer.epno; --将一个record类型的变量赋值给另一个变量。 employer1 := employer; raise info 'employer1 name: % , epno: %',employer1.name, employer1.epno; --将一个record类型变量赋值为NULL。 employer1 := NULL; raise info 'employer1 name: % , epno: %',employer1.name, employer1.epno; --获取record变量的默认值。 raise info 'employer2 name: % ,epno: %', employer2.name, employer2.epno; --在for循环中使用record变量 for employer in select ename,empno from emp_rec order by 1 limit 1 loop raise info 'employer name: % , epno: %', employer.name, employer.epno; end loop; --在select into 中使用record变量。 select ename,empno into employer2 from emp_rec order by 1 limit 1; raise info 'employer name: % , epno: %', employer2.name, employer2.epno; --在cursor中使用record变量。 OPEN C1; FETCH C1 INTO employer2; raise info 'employer name: % , epno: %', employer2.name, employer2.epno; CLOSE C1; RETURN employer.name;END;$$LANGUAGE plpgsql;--调用该函数。gaussdb=# CALL regress_record('abc');--删除函数。gaussdb=# DROP FUNCTION regress_record;--函数表达式return record示例(必须打开兼容性参数proc_outparam_override)set behavior_compat_options = 'proc_outparam_override';create or replace package pkg istype rec_type is record(c1 int, c2 int); function test1(col1 out int,col2 out int) return rec_type;end pkg;/create or replace package body pkg as function test1(col1 out int, col2 out int) return rec_type is r rec_type; begin r.c1:=300; r.c2:=400; col1:=100; col2:=200; return r; end;end pkg;/declare res pkg.rec_type:=pkg.rec_type(); a int; b int;begin res:=pkg.test1(a,b); raise info 'a: %, b: %',a,b; raise info '%', res;end;/-- 打开兼容性参数proc_outparam_override时,返回已定义的record类型,函数可以不需out参数create type rec_type is (c1 int, c2 int);create or replace function func(a in int) return rec_typeas declarer rec_type;beginr.c1:=1;r.c2:=2;return r;end;/call func(0);-- 打开兼容性参数proc_outparam_override时,函数直接返回未定义的record类型时,至少需要带有一个out参数create or replace function func(a in int) return recordas declaretype rc is record(c1 int);r rc;beginr.c1:=1;a:=1;return r;end;/call func(1);
  • 集合MULTISET函数 MULTISET UNION [ALL | DISTINCT] 参数:nesttable类型 返回值:nesttable类型 功能描述:两个集合变量的并集,ALL不去除重复元素,DISTINCT去除重复元素。 示例: gaussdb=# declaregaussdb-# type nest is table of int;gaussdb-# a nest := nest(1,2);gaussdb-# b nest := nest(2,3);gaussdb-# begingaussdb$# a := a MULTISET UNION ALL b;gaussdb$# raise info '%', a;gaussdb$# end;gaussdb$# /INFO: {1,2,2,3}ANONYMOUS BLOCK EXECUTE gaussdb=# declaregaussdb-# type nest is table of int;gaussdb-# a nest := nest(1,2);gaussdb-# b nest := nest(2,3);gaussdb-# begingaussdb$# a := a MULTISET UNION DISTINCT b;gaussdb$# raise info '%', a;gaussdb$# end;gaussdb$# /INFO: {1,2,3}ANONYMOUS BLOCK EXECUTE MULTISET EXCEPT [ALL | DISTINCT] 参数:nesttable类型 返回值:nesttable类型 功能描述:两个集合变量的差集。如A MULTISET EXCEPT B:ALL表示去除A中与B重复的元素;DISTINCT表示先对A进行去重操作,然后去除与B中有重复的元素。 示例: gaussdb=# declaregaussdb-# type nest is table of int;gaussdb-# a nest := nest(1,2,2);gaussdbs-# b nest := nest(2,3);gaussdb-# begingaussdb$# a := a MULTISET EXCEPT ALL b;gaussdb$# raise info '%', a;gaussdb$# end;gaussdb$# /INFO: {1,2}ANONYMOUS BLOCK EXECUTE gaussdb=# declaregaussdb-# type nest is table of int;gaussdb-# a nest := nest(1,2,2);gaussdb-# b nest := nest(2,3);gaussdb-# begingaussdb$# a := a MULTISET EXCEPT DISTINCT b;gaussdb$# raise info '%', a;gaussdb$# end;gaussdb$# /INFO: {1}ANONYMOUS BLOCK EXECUTE MULTISET INTERSECT [ALL | DISTINCT] 参数:nesttable类型 返回值:nesttable类型 功能描述:两个集合变量的交集。如 A MULTISET INTERSECT B:ALL表是取A与B所有重复的元素;DISTINCT表示取A与B中重复元素,且去除重复元素。 示例: gaussdb=# declaregaussdb-# type nest is table of int;gaussdb-# a nest := nest(1,2,2);gaussdbs-# b nest := nest(2,2,3);gaussdb-# begingaussdb$# a := a MULTISET INTERSECT ALL b;gaussdb$# raise info '%', a;gaussdb$# end;gaussdb$# /INFO: {2,2}ANONYMOUS BLOCK EXECUTE gaussdb=# declaregaussdb-# type nest is table of int;gaussdb-# a nest := nest(1,2,2);gaussdb-# b nest := nest(2,2,3);gaussdb-# begingaussdb$# a := a MULTISET INTERSECT DISTINCT b;gaussdb$# raise info '%', a;gaussdb$# end;gaussdb$# /INFO: {2}ANONYMOUS BLOCK EXECUTE
  • 变量声明 变量声明语法请参见图1。 图1 declare_variable::= 对以上语法格式的解释如下: variable_name:变量名。 type:变量类型。 value:该变量的初始值(如果不给定初始值,则初始为NULL)。value也可以是表达式。 示例 123456 gaussdb=# DECLARE emp_id INTEGER := 7788; --定义变量并赋值BEGIN emp_id := 5*7784; --变量赋值END;/
  • 参数说明 GRANT的权限分类如下所示。 SELECT 允许对指定的表、视图、序列执行SELECT命令,update或delete时也需要对应字段上的select权限。 INSERT 允许对指定的表执行INSERT命令。 UPDATE 允许对声明的表中任意字段执行UPDATE命令。通常,update命令也需要select权限来查询出哪些行需要更新。SELECT… FOR UPDATE和SELECT… FOR SHARE除了需要SELECT权限外,还需要UPDATE权限。 DELETE 允许执行DELETE命令删除指定表中的数据。通常,delete命令也需要select权限来查询出哪些行需要删除。 TRUNCATE 允许执行TRUNCATE语句删除指定表中的所有记录。 REFEREN CES 创建一个外键约束,必须拥有参考表和被参考表的REFERENCES权限。 TRIGGER 允许在指定的表上创建触发器。 CREATE 对于数据库,允许在数据库里创建新的模式。 对于模式,允许在模式中创建新的对象。如果要重命名一个对象,用户除了必须是该对象的所有者外,还必须拥有该对象所在模式的CREATE权限。 对于表空间,允许在表空间中创建表,允许在创建数据库和模式的时候把该表空间指定为缺省表空间。 CONNECT 允许用户连接到指定的数据库。 EXECUTE 允许使用指定的函数,以及利用这些函数实现的操作符。 USAGE 对于过程语言,允许用户在创建函数的时候指定过程语言。 对于模式,USAGE允许访问包含在指定模式中的对象,若没有该权限,则只能看到这些对象的名称。 对于序列,USAGE允许使用nextval函数。 对于Data Source对象,USAGE是指访问权限,也是可赋予的所有权限,即USAGE与ALL PRIVILEGES等价。 ALTER 允许用户修改指定对象的属性,但不包括修改对象的所有者和修改对象所在的模式。 DROP 允许用户删除指定的对象。 COMMENT 允许用户定义或修改指定对象的注释。 INDEX 允许用户在指定表上创建索引,并管理指定表上的索引,还允许用户对指定表执行REINDEX和CLUSTER操作。 VACUUM 允许用户对指定的表执行ANALYZE和VACUUM操作。 ALL PRIVILEGES 一次性给指定用户/角色赋予所有可赋予的权限。只有系统管理员有权执行GRANT ALL PRIVILEGES。 GRANT的参数说明如下所示。 role_name 已存在用户名称。 table_name 已存在表名称。 column_name 已存在字段名称。 schema_name 已存在模式名称。 database_name 已存在数据库名称。 function_name 已存在函数名称。 procedure_name 已存在存储过程名称。 sequence_name 已存在序列名称。 domain_name 已存在域类型名称。 fdw_name 已存在外部数据包名称。 lang_name 已存在语言名称。 type_name 已存在类型名称。 src_name 已存在的Data Source对象名称。 argmode 参数模式。 取值范围:字符串,要符合标识符命名规范。 arg_name 参数名称。 取值范围:字符串,要符合标识符命名规范。 arg_type 参数类型。 取值范围:字符串,要符合标识符命名规范。 loid 包含本页的大对象的标识符。 取值范围:字符串,要符合标识符命名规范。 tablespace_name 表空间名称。 client_master_key 客户端加密主密钥的名称。 取值范围:字符串,要符合标识符命名规范。 column_encryption_key 列加密密钥的名称。 取值范围:字符串,要符合标识符命名规范。 directory_name 目录名称。 取值范围:字符串,要符合标识符命名规范。 WITH GRANT OPTION 如果声明了WITH GRANT OPTION,则被授权的用户也可以将此权限赋予他人,否则就不能授权给他人。这个选项不能赋予PUBLIC。 非对象所有者给其他用户授予对象权限时,命令按照以下规则执行: 如果用户没有该对象上指定的权限,命令立即失败。 如果用户有该对象上的部分权限,则GRANT命令只授予他有授权选项的权限。 如果用户没有可用的授权选项,GRANT ALL PRIVILEGES形式将发出一个警告信息,其他命令形式将发出在命令中提到的且没有授权选项的相关警告信息。 数据库系统管理员可以访问所有对象,而不会受对象的权限设置影响。这个特点类似Unix系统的root的权限。和root一样,除了必要的情况外,建议不要总是以系统管理员身份进行操作。
  • 注意事项 不允许将ANY权限授予PUBLIC,也不允许从PUBLIC回收ANY权限。 ANY权限属于数据库内的权限,只对授予该权限的数据库内的对象有效,例如SELECT ANY TABLE只允许用户查看当前数据库内的所有用户表数据,对其他数据库内的用户表无查看权限。 即使用户被授予ANY权限,也不能对私有用户下的对象进行访问操作(INSERT、DELETE、UPDATE、SELECT)。 ANY权限与原有的权限相互无影响。 如果用户被授予CREATE ANY TABLE权限,在同名schema下创建表的属主是该schema的属主,用户对表进行其他操作时,需要授予相应的操作权限。与此类似的还有CREATE ANY FUNCTION、CREATE ANY PACKAGE、CREATE ANY TYPE、CREATE ANY SEQUENCE和CREATE ANY INDEX,在同名模式下创建的对象的属主是同名模式的属主;而对于CREATE ANY TRIGGER和CREATE ANY SYNONYM,在同名模式下创建的对象的属主为创建者。 需要谨慎授予用户CREATE ANY FUNCTION或CREATE ANY PACKAGE的权限,以免其他用户利用DEFINER类型的函数或PACKAGE进行权限提升。 通过GRANT授予用于使用表的权限时,如果用户使用不当,可能通过ALTER语法在表的默认值、约束增加表达式,通过创建索引在INDEX上增加表达式等操作,导致权限被利用的风险。 通过GRANT授予用户使用TRIGGER的权限时,如果用户使用不当,可能通过WHEN条件创建表达式,当触发器被触发时,存在权限被利用的风险。 给用户赋权时,需要特别注意定义者函数/PACKAGE,定义者函数/PACKAGE会使用函数/PACKAGE的owner权限执行,若赋权不当(包括GRANT ROLE TO ROLE),则存在权限被利用风险。
  • 功能描述 对角色和用户进行授权操作。 使用GRANT命令进行用户授权包括以下场景: 将系统权限授权给角色或用户 系统权限又称为用户属性,包括SYSADMIN、CREATEDB、CREATEROLE、AUDITADMIN、MONADMIN、OPRADMIN、POLADMIN、INHERIT、REPLICATION、VCADMIN和 LOG IN等。 系统权限一般通过CREATE/ALTER ROLE语法来指定。其中,SYSADMIN权限可以通过GRANT/REVOKE ALL PRIVILEGE授予或撤销。但系统权限无法通过ROLE和USER的权限被继承,也无法授予PUBLIC。 将数据库对象授权给角色或用户 将数据库对象(表和视图、指定字段、数据库、函数、模式、表空间等)的相关权限授予特定角色或用户; GRANT命令将数据库对象的特定权限授予一个或多个角色。这些权限会追加到已有的权限上。 关键字PUBLIC表示该权限要赋予所有角色,包括以后创建的用户。PUBLIC可以看做是一个隐含定义好的组,它总是包括所有角色。任何角色或用户都将拥有通过GRANT直接赋予的权限和所属的权限,再加上PUBLIC的权限。 如果声明了WITH GRANT OPTION,则被授权的用户也可以将此权限赋予他人,否则就不能授权给他人。这个选项不能赋予PUBLIC,这是 GaussDB Kernel特有的属性。 GaussDB Kernel会将某些类型的对象上的权限授予PUBLIC。默认情况下,对表、表字段、序列、外部数据源、外部服务器、模式或表空间对象的权限不会授予PUBLIC,而以下这些对象的权限会授予PUBLIC:数据库的CONNECT权限和CREATE TEMP TABLE权限、函数的EXECUTE特权、语言和数据类型(包括域)的USAGE特权。当然,对象拥有者可以撤销默认授予PUBLIC的权限并专门授予权限给其他用户。为了更安全,建议在同一个事务中创建对象并设置权限,这样其他用户就没有时间窗口使用该对象。另外可参考安全加固指南的权限控制章节,对PUBLIC用户组的权限进行限制。这些初始的默认权限可以使用ALTER DEFAULT PRIVILEGES命令修改。 对象的所有者缺省具有该对象上的所有权限,出于安全考虑所有者可以舍弃部分权限,但ALTER、DROP、COMMENT、INDEX、VACUUM以及对象的可再授予权限属于所有者固有的权限,隐式拥有。 将角色或用户的权限授权给其他角色或用户 将一个角色或用户的权限授予一个或多个其他角色或用户。在这种情况下,每个角色或用户都可视为拥有一个或多个数据库权限的集合。 当声明了WITH ADMIN OPTION,被授权的用户可以将该权限再次授予其他角色或用户,以及撤销所有由该角色或用户继承到的权限。当授权的角色或用户发生变更或被撤销时,所有继承该角色或用户权限的用户拥有的权限都会随之发生变更。 数据库系统管理员可以给任何角色或用户授予/撤销任何权限。拥有CREATEROLE权限的角色可以赋予或者撤销任何非系统管理员角色的权限。 将ANY权限授予给角色或用户 将ANY权限授予特定的角色和用户,ANY权限的取值范围参见语法格式。当声明了WITH ADMIN OPTION,被授权的用户可以将该ANY权限再次授予其他角色/用户,或从其他角色/用户处回收该ANY权限。ANY权限可以通过角色被继承,但不能赋予PUBLIC。初始用户和三权分立关闭时的系统管理员用户可以给任何角色/用户授予或撤销ANY权限。 目前支持以下ANY权限:CREATE ANY TABLE、ALTER ANY TABLE、DROP ANY TABLE、SELECT ANY TABLE、INSERT ANY TABLE、UPDATE ANY TABLE、DELETE ANY TABLE、CREATE ANY SEQUENCE、CREATE ANY INDEX、CREATE ANY FUNCTION、EXECUTE ANY FUNCTION、 CREATE ANY PACKAGE、EXECUTE ANY PACKAGE、CREATE ANY TYPE、ALTER ANY TYPE、DROP ANY TYPE、ALTER ANY SEQUENCE、DROP ANY SEQUENCE、SELECT ANY SEQUENCE、ALTER ANY INDEX、DROP ANY INDEX、CREATE ANY SYNONYM、DROP ANY SYNONYM、CREATE ANY TRIGGER、ALTER ANY TRIGGER、DROP ANY TRIGGER。详细的ANY权限范围描述参考表1
  • 语法格式 将表或视图的访问权限赋予指定的用户或角色。 GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | ALTER | DROP | COMMENT | INDEX | VACUUM } [, ...] | ALL [ PRIVILEGES ] } ON { [ TABLE ] table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...] } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将表中字段的访问权限赋予指定的用户或角色。 GRANT { {{ SELECT | INSERT | UPDATE | REFERENCES | COMMENT } ( column_name [, ...] )} [, ...] | ALL [ PRIVILEGES ] ( column_name [, ...] ) } ON [ TABLE ] table_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将序列的访问权限赋予指定的用户或角色,LARGE字段属性可选,赋权语句不区分序列是否为LARGE。 GRANT { { SELECT | UPDATE | USAGE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON { [ [ LARGE ] SEQUENCE ] sequence_name [, ...] | ALL SEQUENCES IN SCHEMA schema_name [, ...] } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将数据库的访问权限赋予指定的用户或角色。 GRANT { { CREATE | CONNECT | TEMPORARY | TEMP | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON DATABASE database_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将域的访问权限赋予指定的用户或角色。 GRANT { USAGE | ALL [ PRIVILEGES ] } ON DOMAIN domain_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 本版本暂时不支持赋予域的访问权限。 将客户端加密主密钥CMK的访问权限赋予指定的用户或角色。 1234 GRANT { { USAGE | DROP } [, ...] | ALL [ PRIVILEGES ] } ON CLIENT_MASTER_KEY client_master_key [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将列加密密钥CEK的访问权限赋予指定的用户或角色。 1234 GRANT { { USAGE | DROP } [, ...] | ALL [ PRIVILEGES ] } ON COLUMN_ENCRYPTION_KEY column_encryption_key [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将外部数据源的访问权限赋予给指定的用户或角色。 GRANT { USAGE | ALL [ PRIVILEGES ] } ON FOREIGN DATA WRAPPER fdw_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将外部服务器的访问权限赋予给指定的用户或角色。 GRANT { { USAGE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON FOREIGN SERVER server_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将函数的访问权限赋予给指定的用户或角色。 GRANT { { EXECUTE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON { FUNCTION {function_name ( [ {[ argmode ] [ arg_name ] arg_type} [, ...] ] )} [, ...] | ALL FUNCTIONS IN SCHEMA schema_name [, ...] } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将存储过程的访问权限赋予给指定的用户或角色。 1234 GRANT { { EXECUTE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON { PROCEDURE {proc_name ( [ {[ argmode ] [ arg_name ] arg_type} [, ...] ] )} [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将过程语言的访问权限赋予给指定的用户或角色。 GRANT { USAGE | ALL [ PRIVILEGES ] } ON LANGUAGE lang_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将大对象的访问权限赋予指定的用户或角色。 GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] } ON LARGE OBJECT loid [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 本版本暂时不支持大对象。 将模式的访问权限赋予指定的用户或角色。 GRANT { { CREATE | USAGE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON SCHEMA schema_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将模式中的表或者视图对象授权给其他用户时,需要将表或视图所属的模式的USAGE权限同时授予该用户,若没有该权限,则只能看到这些对象的名称,并不能实际进行对象访问。 同名模式下创建表的权限无法通过此语法赋予,可以通过将角色的权限赋予其他用户或角色的语法,赋予同名模式下创建表的权限。 将表空间的访问权限赋予指定的用户或角色。 GRANT { { CREATE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON TABLESPACE tablespace_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 将类型的访问权限赋予指定的用户或角色。 GRANT { { USAGE | ALTER | DROP | COMMENT } [, ...] | ALL [ PRIVILEGES ] } ON TYPE type_name [, ...] TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ]; 本版本暂时不支持赋予类型的访问权限。 将Data Source对象的权限赋予指定的角色。 1234 GRANT { USAGE | ALL [PRIVILEGES]} ON DATA SOURCE src_name [, ...] TO { [GROUP] role_name | PUBLIC } [, ...] [WITH GRANT OPTION]; 将directory对象的权限赋予指定的角色。 1234 GRANT { { READ | WRITE | ALTER | DROP } [, ...] | ALL [PRIVILEGES] } ON DIRECTORY directory_name [, ...] TO { [GROUP] role_name | PUBLIC } [, ...] [WITH GRANT OPTION]; 将package对象的权限赋予指定的角色。 12345 GRANT { { EXECUTE | ALTER | DROP | COMMENT } [, ...] | ALL [PRIVILEGES] } ON { PACKAGE package_name [, ...] | ALL PACKAGES IN SCHEMA schema_name [, ...] } TO { [GROUP] role_name | PUBLIC } [, ...] [WITH GRANT OPTION]; 将角色的权限赋予其他用户或角色的语法。 GRANT role_name [, ...] TO role_name [, ...] [ WITH ADMIN OPTION ]; 将sysadmin权限赋予指定的角色。 GRANT ALL { PRIVILEGES | PRIVILEGE } TO role_name;
  • 带索引的集合类型 该集合类型将下标和对应成员值以键值对的方式存储在HASH表中,对该类型变量的所有操作实际就是对HASH表的操作。用户无需自行扩展或释放存储空间,仅需通过赋值或delete方式进行存储和删除成员。集合相关操作、说明如下: 类型定义 索引集合类型定义需同时指定成员类型data_type和下标类型indexby_type,其中下标类型仅支持integer和varchar。 变量声明和初始化 索引集合类型声明后存在3种初始化场景:未初始化、初始化为空、初始化指定下标和成员值。其中未初始化和初始化为空场景对变量的效果一致。未初始化或初始化为空后变量不为NULL,后续都可以对变量直接进行赋值。初始化指定下标和成员值场景会将指定的下标和成员值以键值对的形式保存到变量中。 变量赋值 索引集合类型变量赋值分为两种:成员赋值和整体赋值。成员赋值可通过指定下标方式对某个成员赋值,若该成员不存在则直接赋值,若存在则刷新该成员值。整体赋值则会将被赋值变量中原有成员都清空后重新保存新的成员值。整体赋值场景不能给变量赋NULL值,否则报错。 变量取值 通过指定下标方式可获取变量中对应下标的成员值,若通过下标找不到该成员则会返回no data found的错误信息。 非兼容A模式下(参数sql_compatibility值不为A),不支持创建带索引集合类型。 支持在匿名块、存储过程、自定义函数、package中定义带索引集合类型,其作用域各不相同。不支持在schema中定义带索引集合类型。 NOT NULL只支持语法不支持功能。 char、vachar、numeric、float、number等元素类型的范围约束语法创建集合类型,例如:“type t1 is table of numeric(5) index by int; ”只支持语法创建,不支持元素的范围约束功能,功能等同于“type t1 is table of numeric index by int;”。 data_type可以为基础数据类型,或存储过程内定义的record类型,集合类型,数组类型,不支持ref cursor类型。 indexby_type仅支持integer和varchar,其中varchar的长度暂不约束。 未初始化的带索引集合类型变量非NULL。 带索引集合类型变量不能赋NULL值,否则报错。 带索引集合类型变量作为入参不能赋NULL值或''。 不同的带索引集合类型的变量不能相互赋值。即使成员类型和下标类型相同,但集合类型名称不同,也是不同的集合类型。如 TYPE t1 IS TABLE OF int index by int; 和 TYPE t2 IS TABLE OF int index by int; 定义的两个集合类型,t1和t2是不同的集合类型,以其定义的变量不支持相互赋值(作为成员类型时该约束不保证生效,赋值逻辑受父类型影响)。 带索引集合类型不支持关系运算和算数运算操作。 select ... bulk collect into 方式赋值带索引集合类型变量时,只支持下标为integer类型的集合类型,下标为varchar类型集合不支持。 支持带索引集合类型变量作为函数的参数和返回值,此时要求参数或者返回值的类型是在package中定义的集合类型。 带索引的集合作为函数入参时,可以传入对应子元素类型相同的数组类型作为入参,不支持多维数组,不支持索引类型为varchar(过时的方法,不建议使用该功能。可执行“set behavior_compat_options = 'disable_rewrite_nesttable';”禁用)。 类型构造器目前仅支持集合类型,其参数个数的上限与用户自定义函数参数个数上限相同。对于带索引的集合类型,构造器在使用时索引的值仅支持为常量。 不支持对XML类型数据操作。 集合类型以及嵌套集合的类型不支持作为表中的一列来创建表。 集合类型的构造器不支持浮点数以及表达式作为下标。
  • 基本语句 在编写PL/SQL过程中,会定义一些变量,给变量赋值,调用其他存储过程等。介绍PL/SQL中的基本语句,包括定义变量、赋值语句、调用语句以及返回语句。 尽量不要在存储过程中调用包含密码的SQL语句,因为存储在数据库中的存储过程文本可能被其他有权限的用户看到导致密码信息被泄漏。如果存储过程中包含其他敏感信息也需要配置存储过程的访问权限,保证敏感信息不会泄漏。 定义变量 赋值语句 调用语句 父主题: 存储过程
  • 结构 PL/SQL块中可以包含子块,子块可以位于PL/SQL中任何部分。PL/SQL块的结构如下: 声明部分:声明PL/SQL用到的变量、类型、游标、局部的存储过程和函数。 DECLARE 不涉及变量声明时声明部分可以没有。 对匿名块来说,没有变量声明部分时,可以省去DECLARE关键字。 对存储过程来说,没有DECLARE, AS相当于DECLARE。即便没有变量声明的部分,关键字AS也必须保留。 执行部分:过程及SQL语句,程序的主要部分。必选。 BEGIN 执行异常部分:错误处理。可选。 EXCEPTION 结束 END;/ 禁止在PL/SQL块中使用连续的Tab,连续的Tab可能会造成在使用gsql工具带“-r”参数执行PL/SQL块时出现异常。
  • 数据类型转换 数据库中允许有些数据类型进行隐式类型转换(赋值、函数调用的参数等),有些数据类型间不允许进行隐式数据类型转换,可尝试使用GaussDB Kernel提供的类型转换函数,例如CAST进行数据类型强转。 GaussDB Kernel数据库常见的隐式类型转换,请参见表1。 GaussDB Kernel支持的DATE的效限范围是:公元前4713年到公元294276年。 表1 隐式类型转换表 原始数据类型 目标数据类型 备注 CHAR VARCHAR2 - CHAR NUMBER 原数据必须由数字组成。 CHAR DATE 原数据不能超出合法日期范围。 CHAR RAW - CHAR CLOB - VARCHAR2 CHAR - VARCHAR2 NUMBER 原数据必须由数字组成。 VARCHAR2 DATE 原数据不能超出合法日期范围。 VARCHAR2 CLOB - NUMBER CHAR - NUMBER VARCHAR2 - DATE CHAR - DATE VARCHAR2 - RAW CHAR - RAW VARCHAR2 - CLOB CHAR - CLOB VARCHAR2 - CLOB NUMBER 原数据必须由数字组成。 INT4 CHAR - INT4 BOOLEAN - BOOLEAN INT4 - 父主题: 存储过程
  • 示例 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536 --演示在存储过程中对数组进行操作。gaussdb=# CREATE OR REPLACE PROCEDURE array_proc ASDECLARE TYPE ARRAY_INTEGER IS VARRAY(1024) OF INTEGER;--定义数组类型 ARRINT ARRAY_INTEGER := ARRAY_INTEGER(); --声明数组类型的变量 BEGIN ARRINT.extend(10); FOR I IN 1..10 LOOP ARRINT(I) := I; END LOOP; DBE_OUTPUT.PRINT_LINE(ARRINT.COUNT); DBE_OUTPUT.PRINT_LINE(ARRINT(1)); DBE_OUTPUT.PRINT_LINE(ARRINT(10)); DBE_OUTPUT.PRINT_LINE(ARRINT(ARRINT.FIRST)); DBE_OUTPUT.PRINT_LINE(ARRINT(ARRINT.LAST)); DBE_OUTPUT.PRINT_LINE(ARRINT(ARRINT.NEXT(ARRINT.FIRST))); DBE_OUTPUT.PRINT_LINE(ARRINT(ARRINT.PRIOR(ARRINT.LAST))); ARRINT.TRIM(); IF ARRINT.EXISTS(10) THEN DBE_OUTPUT.PRINT_LINE('Exist 10th element'); ELSE DBE_OUTPUT.PRINT_LINE('Not exist 10th element'); END IF; DBE_OUTPUT.PRINT_LINE(ARRINT.COUNT); DBE_OUTPUT.PRINT_LINE(ARRINT(ARRINT.FIRST)); DBE_OUTPUT.PRINT_LINE(ARRINT(ARRINT.LAST)); ARRINT.DELETE();END; /--调用该存储过程。gaussdb=# CALL array_proc();--删除存储过程。gaussdb=# DROP PROCEDURE array_proc;
  • 数组类型的使用 在使用数组之前,需要自定义一个数组类型。 在存储过程中紧跟AS关键字后面定义数组类型。定义方法如下。 TYPE array_type IS VARRAY(size) OF data_type; 其中: array_type:要定义的数组类型名。 VARRAY:表示要定义的数组类型。 size:取值为正整数,表示可以容纳的成员的最大数量。 data_type:要创建的数组中成员的类型。 在GaussDB Kernel中,数组会自动增长,访问越界会返回一个NULL,不会报错。 在存储过程中定义的数组类型,其作用域仅在该存储过程中。 size只支持语法,不支持功能。 data_type也可以为存储过程中定义的record类型(匿名块不支持)、集合类型,但不可以为存储过程中定义的数组类型、游标类型。 data_type为集合类型时,不支持使用多维数组。 不支持NOT NULL语法。 array类型的构造器仅支持在O兼容模式下使用。 不支持array类型的构造器作为函数或存储过程参数的默认值。 当data_type为varchar、numeric等可以定义长度和精度的类型,如果package内创建varray类型数组,则在package外部调用该varray类型数组时,varchar、numeric等长度或精度限制会失效。 GaussDB Kernel支持使用圆括号来访问数组元素,且还支持一些特有的函数,如extend、count、first、last、prior、exists、 trim、next、delete来访问数组的内容。 存储过程中如果有DML语句(SELECT、UPDATE、INSERT、DELETE),DML语句推荐使用中括号来访问数组元素,使用小括号默认识别为数组访问,若数组不存在,则识别为函数表达式。 慎用delete删除单个元素功能,会造成元素顺序错乱。 如果clob类型大于1GB,则存储过程中的table of类型、record类型、clob作为出入参、游标、raise info等功能不支持。
  • 语法格式 查询数据 [ WITH [ RECURSIVE ] with_query [, ...] ]SELECT [/*+ plan_hint */] [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]{ * | {expression [ [ AS ] output_name ]} [, ...] }[ into_option ][ FROM from_item [, ...] ][ WHERE condition ][ [ START WITH condition ] CONNECT BY [NOCYCLE] condition [ ORDER SIBLINGS BY expression ] ][ GROUP BY grouping_element [, ...] ][ HAVING condition [, ...] ][ WINDOW {window_name AS ( window_definition )} [, ...] ][ { UNION | INTERSECT | EXCEPT | MINUS } [ ALL | DISTINCT ] select ][ ORDER BY {expression [ [ ASC | DESC | USING operator ] | nlssort_expression_clause ] [ NULLS { FIRST | LAST } ]} [, ...] ][ LIMIT { [offset,] count | ALL } ][ OFFSET start [ ROW | ROWS ] ][ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ][ into_option ][ {FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF table_name [, ...] ] [ NOWAIT | WAIT N ]} [...] ][into_option]; condition和expression中可以使用targetlist中表达式的别名。 只能同一层引用。 只能引用targetlist中的别名。 只能是后面的表达式引用前面的表达式。 不能包含volatile函数。 不能包含Window function函数。 不支持在join on条件中引用别名。 targetlist中有多个要应用的别名则报错。 其中子查询with_query为: with_query_name [ ( column_name [, ...] ) ] AS [ [ NOT ] MATERIALIZED ] ( {select | values | insert | update | delete} ) 其中into字句为: into_option: { INTO var_name [, var_name] ...| INTO OUTFILE 'file_name'[CHARACTER SET charset_name]export_options| INTO DUMPFILE 'file_name'}export_options: { [FIELDS [TERMINATED BY 'string'] [[OPTIONALLY] ENCLOSED BY 'char'] [ESCAPED BY 'char' ] ] [LINES [STARTING BY 'string'] [TERMINATED BY 'string'] ]} 其中指定查询源from_item为: {[ ONLY ] table_name [ * ] [ partition_clause ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ][ TABLESAMPLE sampling_method ( argument [, ...] ) [ REPEATABLE ( seed ) ] ][ TIMECAPSULE {TIMESTAMP | CS N} expression ]|( select ) [ AS ] alias [ ( column_alias [, ...] ) ]|with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]|function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...] | column_definition [, ...] ) ]|function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )|from_item unpivot_clause|from_item pivot_clause|from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]} 其中group子句为: ( )| expression| ( expression [, ...] )| ROLLUP ( { expression | ( expression [, ...] ) } [, ...] )| CUBE ( { expression | ( expression [, ...] ) } [, ...] )| GROUPING SETS ( grouping_element [, ...] ) 其中指定分区partition_clause为: PARTITION { ( partition_name ) | FOR ( partition_value [, ...] ) } |SUBPARTITION { ( subpartition_name ) | FOR ( subpartition_value [, ...] )} 指定分区只适合分区表。 其中设置排序方式nlssort_expression_clause为: NLSSORT ( column_name, ' NLS_SORT = { SCHINESE_PINYIN_M | generic_m_ci } ' )其中,第二个参数可选generic_m_ci,仅支持纯英文不区分大小写排序。 简化版查询语法,功能相当于select * from table_name。 TABLE { ONLY {(table_name)| table_name} | table_name [ * ]};
  • 存储过程 商业规则和业务逻辑可以通过程序存储在GaussDB Kernel中,这个程序就是存储过程。 存储过程是SQL和PL/SQL的组合。存储过程使执行商业规则的代码可以从应用程序中移动到数据库。从而,代码存储一次能够被多个程序使用。 存储过程的创建及调用办法请参考CREATE PROCEDURE。 PL/pgSQL语言函数节所提到的PL/pgSQL语言创建的函数与存储过程的应用方法相通。下面各节中,除非特别声明,否则内容通用于存储过程和PL/pgSQL语言函数。 父主题: 存储过程
  • 数据类型 数据类型是一组值的集合以及定义在这个值集上的一组操作。GaussDB Kernel数据库是由表的集合组成的,而各表中的列定义了该表,每一列都属于一种数据类型,GaussDB Kernel根据数据类型有相应函数对其内容进行操作,例如GaussDB Kernel可对数值型数据进行加、减、乘、除操作。 XML类型数据支持作为存储过程的入参,出参,自定义变量,返回值。支持自治事务的存储过程。 父主题: 存储过程
  • 扩展语法 GaussDB Kernel提供的扩展语法如下。 表1 扩展SQL语法 类别 语法关键字 描述 创建表CREATE TABLE INHERITS ( parent_table [, ... ] ) 支持继承表。 column_constraint: REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ][ ON DELETE action ] [ ON UPDATE action ] 支持用REFERENCES reftable[ ( refcolumn ) ] [ MATCH FULL |MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE action ] [ ON UPDATE action ] 为表创建外键约束。 加载模块 CREATE EXTENSION 把一个新的模块加载进当前数据库中。当前特性是实验室特性,使用时请联系华为工程师提供技术支持。 DROP EXTENSION 删除已加载的模块。当前特性是实验室特性,使用时请联系华为工程师提供技术支持。 聚集函数 CREATE AGGREGATE 定义一个新的聚集函数。 ALTER AGGREGATE 修改一个聚集函数的定义。 DROP AGGREGATE 删除一个现存的聚集函数。 父主题: 附录
  • PL/pgSQL语言函数 PL/pgSQL是一种可载入的过程语言。 用PL/pgSQL创建的函数可以被用在任何可以使用内建函数的地方。例如,可以创建复杂条件的计算函数并且后面用它们来定义操作符或把它们用于索引表达式。 SQL被大多数数据库用作查询语言。它是可移植的并且容易学习。但是每一个SQL语句必须由数据库服务器单独执行。 这意味着客户端应用必须发送每一个查询到数据库服务器、等待它被处理、接收并处理结果、做一些计算,然后发送更多查询给服务器。如果客户端和数据库服务器不在同一台机器上,则会引起进程间通信并且将带来网络负担。 通过PL/pgSQL,可以将一整块计算和一系列查询分组在数据库服务器内部,这样就有了一种过程语言的能力并且使SQL更易用,同时能节省客户端/服务器通信开销。 客户端和服务器之间的额外往返通信被消除。 客户端不需要的中间结果不必被整理或者在服务器和客户端之间传送。 多轮的查询解析可以被避免。 PL/pgSQL可以使用SQL中所有的数据类型、操作符和函数。一些常见函数,例如gs_extend_library。 应用PL/pgSQL创建函数的语法为CREATE FUNCTION。PL/pgSQL是一种可载入的过程语言。其应用方法与存储过程相似,只是存储过程无返回值,函数有返回值。 XML类型数据支持作为自定义函数的入参,出参,自定义变量,返回值。 父主题: 用户自定义函数
  • 使用分区表 分区表是把逻辑上的一张表根据某种方案分成几张物理块进行存储。这张逻辑上的表称之为分区表,物理块称之为分区。分区表是一张逻辑表,不存储数据,数据实际是存储在分区上的。分区表和普通表相比具有以下优点: 改善查询性能:对分区对象的查询可以仅搜索自己关心的分区,提高检索效率。 增强可用性:如果分区表的某个分区出现故障,表在其他分区的数据仍然可用。 方便维护:如果分区表的某个分区出现故障,需要修复数据,只修复该分区即可。 GaussDB Kernel数据库支持的分区表为一级分区表和二级分区表,其中一级分区表包括范围分区表、间隔分区表、列表分区表、哈希分区表四种,二级分区表包括范围分区、列表分区、哈希分区两两组合的九种。 范围分区表:将数据基于范围映射到每一个分区,这个范围是由创建分区表时指定的分区键决定的。这种分区方式是最为常用的,并且分区键经常采用日期,例如将销售数据按照月份进行分区。 间隔分区表:是一种特殊的范围分区表,相比范围分区表,新增间隔值定义,当插入记录找不到匹配的分区时,可以根据间隔值自动创建分区。 列表分区表:将数据中包含的键值分别存储再不同的分区中,依次将数据映射到每一个分区,分区中包含的键值由创建分区表时指定。 哈希分区表:将数据根据内部哈希算法依次映射到每一个分区中,包含的分区个数由创建分区表时指定。 二级分区表:由范围分区、列表分区、哈希分区任意组合得到的分区表,其一级分区和二级分区均可以使用前面三种定义方式。 父主题: 表设计最佳实践
  • 选择存储模型 进行数据库设计时,表设计上的一些关键项将严重影响后续整库的查询性能。表设计对数据存储也有影响:好的表设计能够减少I/O操作及最小化内存使用,进而提升查询性能。 表的存储模型选择是表定义的第一步。客户业务属性是表的存储模型的决定性因素,依据下面表格选择适合当前业务的存储模型。 存储模型 适用场景 行存 点查询(返回记录少,基于索引的简单查询)。 增删改比较多的场景。 列存 统计分析类查询(group , join多的场景)。 父主题: 表设计最佳实践
  • 选择数据类型 高效数据类型,主要包括以下三方面: 尽量使用执行效率比较高的数据类型 一般来说整型数据运算(包括=、>、<、≧、≦、≠等常规的比较运算,以及group by)的效率比字符串、浮点数要高。比如某客户场景中对列存表进行点查询,filter条件在一个numeric列上,执行时间为10+s;修改numeric为int类型之后,执行时间缩短为1.8s左右。 尽量使用短字段的数据类型 长度较短的数据类型不仅可以减小数据文件的大小,提升I/O性能;同时也可以减小相关计算时的内存消耗,提升计算性能。比如对于整型数据,如果可以用smallint就尽量不用int,如果可以用int就尽量不用bigint。 使用一致的数据类型 表关联列尽量使用相同的数据类型。如果表关联列数据类型不同,数据库必须动态地转化为相同的数据类型进行比较,这种转换会带来一定的性能开销。 父主题: 表设计最佳实践
  • 美元引用的字符串常量 如果在字符串序列中包含有'(单引号),那么应当将'(单引号)加倍为''(两个单引号)否则sql语句很可能无法执行。 如果字符串中包含很多单引号或者反斜杠,那么理解字符串的内容可能就会变得很苦涩,并且容易出错,因为单引号都要加倍。 为了让这种场合下的查询更具可读性,我们允许另外一种称作"美元符界定"的字符串常量书写办法。一个通过美元符界定声明的字符串常量由一个美元符号($)、零个或多个字符组成的"记号"、另一个美元符号、组成字符串常量的任意字符序列、一个美元符号、与前面相同的记号、一个美元符号组成的。 gaussdb=# select $$it's an example$$; ?column? ----------------- it's an example(1 row) 父主题: 附录
  • 扩展性 GIN索引的接口实现了一个高层次的抽象,要求访问用户仅需要实现被访问数据类型的语义。GIN层自身可以处理并发操作、记录日志、搜索树结构的任务。 定义GIN索引的访问方式所要做的事情就是实现多个用户定义的方法,这些方法定义了键在树中的行为、键与键之间的关系、需要索引的item、能够使用索引的查询。简而言之,GIN索引将扩展性与普遍性、代码重用、清晰的接口结合在了一起。 实现GIN索引的操作符类有如下四个方法: int compare(Datum a, Datum b) 比较两个key(不是索引的item)然后返回一个小于零、零或大于零的值,分别表示第一个key小于、等于或大于第二个key。NULL不会被传入这个函数。 Datum *extractValue(Datum itemValue, int32 *nkeys, bool **nullFlags) 给定一个要被索引的item,返回一个对应key的数组。返回key的数目必须存储在*nkeys中。如果任何key都可能为NULL,还要分配包含*nkeys个布尔元素的数组,将地址存储到*nullFlags,并且根据需要设置NULL值。 如果所有key都是非NULL,可以让*nullFlags保持为NULL(他的初始值)。如果item不包含任何key,返回值可以为NULL。 Datum *extractQuery(Datum query, int32 *nkeys, StrategyNumber n, bool **pmatch, Pointer **extra_data, bool **nullFlags, int32 *searchMode) 给定一个被查询的值,返回一个对应的key的数组。也就是说,query是可索引操作符右侧的值,而该操作符左侧是被索引的字段。 n是操作符类中操作符的策略号。通常,extractQuery需要参考n来决定query的数据类型以及抽取键值的方法。返回key的个数必须存放在*nkeys中。如果任何key都可能为NULL,还要分配包含*nkeys个布尔元素的数组,将地址存储到*nullFlags,并且根据需要设置NULL值。 如果所有key都是非NULL的,可以让*nullFlags保持为NULL(他的初始值)。如果query不包含任何key,返回值可以为NULL。 searchMode是一个输出参数,他允许extractQuery指定一些关于如何执行搜索的细节。如果设置*searchMode为GIN_SEARCH_MODE_DEFAULT(这也是调用函数前此参数的初始化值),只有那些至少返回一个key的item才能被考虑作为候选匹配项。如果设置*searchMode为GIN_SEARCH_MODE_INCLUDE_EMPTY,除了包含至少一个匹配key的item之外,根本不包含任何key的item也被考虑作为候选匹配项。(这个模式对于实现像“是否是子集”这样的操作是有用的)如果设置*searchMode为GIN_SEARCH_MODE_ALL,索引中所有非NULL的item都被考虑作为候选匹配项,不管他们是否匹配返回key中的任何一个。 pmatch是一个允许支持部分匹配的输出参数。如果使用此参数,extractQuery必须分配有*nkeys个布尔元素的数组,并把数组地址保存到*pmatch。如果需要部分匹配相应的key,则数组的每个元素应该设置为TRUE;如果不需要匹配,则设置为FALSE。如果设置*pmatch为NULL,则假设GIN不需要部分匹配。在函数调用前这个值被初始化为NULL,因此,对于不支持部分匹配的操作符类,可以忽略这个参数。 extra_data是一个允许extractQuery以consistent和comparePartial的方式传递额外数据的输出参数。如果使用他,extractQuery必须分配一个包含*nkeys个Pointer元素的数组,并把数组地址保存到*extra_data,然后把他想附加的东西存储到各个独立的指针中。在函数调用前这个值初始化为NULL,因此,对于不需要附加数据的操作符类,可以忽略这个参数。如果设置了*extra_data,那么以consistent方式传递整个数组,使用comparePartial方式传递适当的元素。 bool consistent(bool check[], StrategyNumber n, Datum query, int32 nkeys, Pointer extra_data[], bool *recheck, Datum queryKeys[], bool nullFlags[]) 如果被索引项满足StrategyNumber为n的查询操作符则返回TRUE。这个函数并不直接访问被索引项的值,因为GIN并没有精确的把项目保存下来,但是需要知道从查询中提取的哪些键值出现在给定的被索引项中。 check数组的长度是nkeys,这个与query调用extractQuery函数返回的键值的数目相同。如果索引项包含了相应的查询键,check数组中对应的元素值就是TRUE。比如,如果(check[i] == TRUE),那么意味着extractQuery的结果数组的第i个键出现在索引项中。考虑可能会用到consistent方式,原始的query也被作为参数传入进来。与此相同的还有extractQuery函数返回的queryKeys[]和nullFlags[]。 extra_data是extractQuery函数返回的额外数据数组,如果没有的话就是NULL。 当extractQuery在queryKeys[]中返回一个NULL的键值,如果被索引项包含NULL键值,相应的check[]中的元素是TRUE。也就是说,check[]的语义很像IS NOT DISTINCT FROM。如果需要知道是通常值匹配还是NULL匹配,consistent函数可以检查相应的nullFlags[]元素。 成功执行后,如果堆元组需要针对查询运算符进行重新检查,*recheck需要设置为TRUE,如果索引测试已经是精确的了,则设为FALSE。也就是说,FALSE的返回值确保堆元组不匹配这个查询;设置*recheck为FALSE的TRUE的返回值确保堆元组匹配这个查询;设置*recheck为TRUE的TRUE的返回值意味着堆元组可能匹配这个查询,因此需要通过直接对照原始索引项对查询运算符进行获取和重新检查。 GIN操作符类可以可选地提供第五个函数。 int comparePartial(Datum partial_key, Datum key, StrategyNumber n, Pointer extra_data) 比较一个部分匹配查询键和一个索引键。返回一个整型值,它的符号代表了不同的含义:小于0意味着索引键不匹配查询,但是索引扫描应该继续; 0意味着索引键匹配查询;大于0指示应该终止索引扫描,因为不可能再有更多的匹配。在需要确定何时结束扫描的语义的情况下,这里提供了生成部分一致查询的操作符的策略号n。同样的,extra_data是extractQuery生成的额外数据数组中的相应元素,如果没有对应的元素,则为NULL。 NULL的键永远不会被传入这个函数。 为了支持"部分匹配"查询,一个操作符类必须提供comparePartial方法,并且当遇到部分匹配查询时,他的extractQuery方法必须设置pmatch参数。详细信息请参考部分匹配算法。 上面的各种Datum值的实际数据类型根据操作符类的不同而不同。传入到extractValue中的项目值总是操作符类的输入类型,所有的键值类型必须是这个类的STORAGE类型。传入到extractQuery和consistent的query参数的类型是由策略号识别的类成员操作符的右操作数的输入类型。他不需要和项目类型相同,只要可以从中抽取出正确类型的键值。 父主题: GIN索引
  • GIN提示与技巧 创建vs插入 由于可能要为每个项目插入很多键,所以GIN索引的插入可能比较慢。对于向表中大量插入的操作,我们建议先删除GIN索引,在完成插入之后再重建索引。与GIN索引创建、查询性能相关的GUC参数如下: maintenance_work_mem GIN索引的构建时间对maintenance_work_mem的设置非常敏感。 work_mem 在向启用了FASTUPDATE的GIN索引执行插入操作的期间,只要待处理实体列表的大小超过了work_mem,系统就会清理这个列表。为了避免可观察到的响应时间的大起大落,让待处理实体列表在后台被清理是比较合适的(比如通过autovacuum)。前端清理操作可以通过增加work_mem或者执行autovacuum来避免。然而,扩大work_mem意味着如果发生了前端清理,那么他的执行时间将更长。 gin_fuzzy_search_limit 开发GIN索引的主要目的是为了让GaussDB Kernel支持高度可伸缩的全文索引,并且常常会遇见全文索引返回海量结果的情形。而且,这经常发生在查询高频词的时候,因而这样的结果集没什么用处。因为从磁盘读取大量记录并对其进行排序会消耗大量资源,这在产品环境下是不能接受的。为了控制这种情况,GIN索引有一个可配置的返回结果行数的软上限的配置参数gin_fuzzy_search_limit。缺省值0表示没有限制。如果设置了非零值,那么返回结果就是从完整结果集中随机选择的一部分。"软上限"的意思是返回结果的实际数量可能与指定的限制有偏差,这取决于查询和系统随机数生成器的质量。 父主题: GIN索引
共100000条