华为云用户手册

  • 注意事项 不能回滚到一个未定义的保存点,语法上会报错。 在保存点方面,游标有一些非事务性的行为。任何在保存点里打开的游标都会在回滚掉这个保存点之后关闭。如果一个前面打开了的游标在保存点里面,并且游标被一个FETCH命令影响,而这个保存点稍后回滚了,那么这个游标的位置仍然在FETCH让它指向的位置(也就是FETCH不会被回滚)。关闭一个游标的行为也不会被回滚给撤销掉。如果一个游标的操作导致事务回滚,那么这个游标就会置于不可执行状态,所以,尽管一个事务可以用ROLLBACK TO SAVEPOINT重新恢复,但是游标不能再使用了。 使用ROLLBACK TO SAVEPOINT回滚到一个保存点。使用RELEASE SAVEPOINT删除一个保存点,但是保留该保存点建立后执行的命令的效果。
  • 示例 1 2 3 4 5 6 7 8 9101112131415161718 --撤销 my_savepoint 建立之后执行的命令的影响。gaussdb=# START TRANSACTION;gaussdb=# SAVEPOINT my_savepoint;gaussdb=# ROLLBACK TO SAVEPOINT my_savepoint;--游标位置不受保存点回滚的影响。gaussdb=# DECLARE foo CURSOR FOR SELECT 1 UNION SELECT 2;gaussdb=# SAVEPOINT foo;gaussdb=# FETCH 1 FROM foo; ?column? ---------- 1gaussdb=# ROLLBACK TO SAVEPOINT foo;gaussdb=# FETCH 1 FROM foo; ?column? ---------- 2gaussdb=# RELEASE SAVEPOINT my_savepoint;gaussdb=# COMMIT;
  • 参数说明 configuration_parameter 运行时参数的名称。 取值范围:可以使用SHOW ALL命令查看运行时参数。 部分通过SHOW ALL查看的参数不能通过SET设置。如max_datanodes。 CURRENT_SCHEMA 当前模式 TIME ZONE 时区。 TRANSACTION ISOLATION LEVEL 事务的隔离级别。 SESSION AUTHORIZATION 当前会话的用户标识符。 ALL 所有运行时参数。
  • 美元引用的字符串常量 如果在字符串序列中包含有'(单引号),那么应当将'(单引号)加倍为''(两个单引号)否则sql语句很可能无法执行。 如果字符串中包含很多单引号或者反斜杠,那么理解字符串的内容可能就会变得很苦涩,并且容易出错,因为单引号都要加倍。 为了让这种场合下的查询更具可读性,我们允许另外一种称作"美元符界定"的字符串常量书写办法。一个通过美元符界定声明的字符串常量由一个美元符号($)、零个或多个字符组成的"记号"、另一个美元符号、组成字符串常量的任意字符序列、一个美元符号、与前面相同的记号、一个美元符号组成的。 gaussdb=# SELECT $$it's an example$$; ?column? ----------------- it's an example(1 row) 父主题: 附录
  • 语法格式 12345 VALUES {( expression [, ...] )} [, ...] [ ORDER BY { sort_expression [ ASC | DESC | USING operator ] } [, ...] ] [ LIMIT { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ];
  • 参数说明 expression 用于计算或插入结果表指定地点的常量或者表达式。 在一个出现在INSERT顶层的VALUES列表中,expression可以被DEFAULT替换以表示插入目的字段的缺省值。除此以外,当VALUES出现在其他场合的时候是不能使用DEFAULT的。 sort_expression 一个表示如何排序结果行的表达式或者整数常量。 ASC 指定按照升序排列。 DESC 指定按照降序排列。 operator 一个排序操作符。 count 返回的最大行数。 OFFSET start [ ROW | ROWS ] 声明返回的最大行数,而start声明开始返回行之前忽略的行数。 FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY FETCH子句限定返回查询结果从第一行开始的总行数,count的缺省值为1。
  • 语法格式 为当前会话设置会话用户标识符和当前用户标识符。 1 SET [ SESSION | LOCAL ] SESSION AUTHORIZATION role_name PASSWORD 'password'; 重置会话和当前用户标识符为初始认证的用户名。 12 {SET [ SESSION | LOCAL ] SESSION AUTHORIZATION DEFAULT | RESET SESSION AUTHORIZATION};
  • 参数说明 SESSION 声明这个命令只对当前会话起作用。 LOCAL 声明该命令只在当前事务中有效。 role_name 用户名。 取值范围:字符串,要符合标识符命名规范。 password 角色的密码。要求符合密码的命名规则。 使用密文密码限制如下: 管理员用户不能使用密文密码切换到其他管理员用户,只能向权限更低用户切换。 使用密文密码通常用于gs_dump、gs_dumpall导出场景,其他场景不建议直接使用密文密码。 DEFAULT 重置会话和当前用户标识符为初始认证的用户名。
  • 选择分布列 Hash分布表的分布列选取至关重要,需要满足以下原则: 列值应比较离散,以便数据能够均匀分布到各个DN。例如,考虑选择表的主键为分布列,如在人员信息表中选择身份证号码为分布列。 在满足上述条件的情况下,考虑选择查询中的连接条件为分布列,以便Join任务能够下推到DN中执行,且减少DN之间的通信数据量。 对于Hash分表策略,如果分布列选择不当,可能导致数据倾斜,查询时出现部分DN的I/O短板,从而影响整体查询性能。因此在采用Hash分表策略之后需对表的数据进行数据倾斜性检查,以确保数据在各个DN上是均匀分布的。可以使用以下SQL检查数据倾斜性: 1234 SELECT xc_node_id, count(1) FROM tablenameGROUP BY xc_node_id ORDER BY xc_node_id DESC; 示例: CREATE TABLE t1(c1 int) distribute by hash(c1);INSERT INTO t1 values(generate_series(1,100));select xc_node_id, count(1) from t1 group by xc_node_id order by xc_node_id desc;DROP TABLE t1; 其中xc_node_id对应DN,一般来说,不同DN的数据量相差5%以上即可视为倾斜,如果相差10%以上就必须要调整分布列。 GaussDB 支持多分布列特性,可以更好地满足数据分布的均匀性要求。 Range/List分布表的分布列由用户根据实际需要进行选择。除了需选择合适的分布列,还需要注意分布规则对数据分布的影响。 父主题: 表设计最佳实践
  • 参数说明 new_table new_table指定新建表的名称。 UN LOG GED 指定表为非日志表。非日志表中写入的数据不会被写入到预写日志中,比普通表快很多。但是,非日志表在冲突或异常关机后会被自动删截,非日志表中的内容也不会被复制到备用服务器中,在该类表中创建的索引也不会被自动记录。 使用场景:非日志表不能保证数据的安全性,用户应该在确保数据已经做好备份的前提下使用,例如系统升级时进行数据的备份。 故障处理:当异常关机等操作导致非日志表上的索引发生数据丢失时,用户应该对发生错误的索引进行重建。 SELECT INTO的其它参数可参考SELECT的参数说明。
  • 语法格式 1 2 3 4 5 6 7 8 9101112131415 [ WITH [ RECURSIVE ] with_query [, ...] ]SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ] { * | {expression [ [ AS ] output_name ]} [, ...] } INTO [ UNLOGGED ] [ TABLE ] new_table [ FROM from_item [, ...] ] [ WHERE condition ] [ GROUP BY expression [, ...] ] [ 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 { count | ALL } ] [ OFFSET start [ ROW | ROWS ] ] [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ] [ {FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT | WAIT N]} [...] ];
  • 参数说明 INDEX 重新建立指定的索引。 TABLE 重新建立指定表的所有索引,如果表有从属的“TOAST”表,则这个表也会重建索引。如果表上有索引已经被alter unusable失效,则这个索引无法被重新创建。当指定CONCURRENTLY选项时,暂不支持重建从属“TOAST”表上的索引。 DATABASE 重建当前数据库里的所有索引。当指定CONCURRENTLY选项时,暂不支持重建数据库中表的从属“TOAST”表上的索引。 SYSTEM 在当前数据库上重建所有系统表上的索引。不会处理在用户表上的索引。 CONCURRENTLY 以不阻塞DML的方式重建索引(加ShareUpdateExclusiveLock锁)。重建索引时,一般会阻塞其他语句对该索引所依赖表的访问。指定此关键字,可以实现重建过程中不阻塞DML。不支持在线重建系统表上的索引。不支持REINDEX INTERNAL TABLE CONCURRENTLY和REINDEX SYSTEM CONCURRENTLY。当执行REINDEX DATABASE CONCURRENTLY时,在线重建当前数据库中用户表上的所有索引(不会处理系统表上的索引)。REINDEX CONCURRENTLY不可以在事务内执行。在线重建索引只支持B-tree索引和UB-tree索引,只支持普通索引、GLOBAL索引、LOCAL索引。在线并行重建索引只支持Astore的普通索引、GLOBAL索引、LOCAL索引,Ustore索引不支持在线并行重建。如果在线重建索引失败,可能会留下非法的新索引,在系统无法自动清理失败新索引的情况下(比如数据库宕机),需要尽快手动清除(使用DROP INDEX语句)非法新索引,以防占用更多资源。一般来说,非法的新索引的后缀名为_ccnew。REINDEX INDEX CONCURRENTLY对表加4级会话锁,且其前几个阶段与CREATE INDEX CONCURRENTLY相似,因此也可能产生卡住或死锁的问题,具体场景与CREATE INDEX CONCURRENTLY相似(比如两个会话同时对同一个索引或表进行REINDEX CONCURRENTLY操作,会引发死锁问题),详见CONCURRENTLY章节。 name 需要重建索引的索引、表、数据库的名称。表和索引可以有模式修饰。 REINDEX DATABASE和SYSTEM只能重建当前数据库的索引,所以name必须和当前数据库名称相同。 FORCE 废弃选项,仅为保持前向兼容,故继续保留。 partition_name 需要重建索引的分区的名称或者索引分区的名称。 取值范围: 如果前面是REINDEX INDEX,则这里应该指定索引分区的名称; 如果前面是REINDEX TABLE,则这里应该指定分区的名称; REINDEX DATABASE和SYSTEM这种形式的重建索引不能在事务块中执行。 REINDEX、REINDEX CONCURRENTLY不支持单独操作toast表或toast索引。
  • 示例 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031 --创建存储过程proc_add。gaussdb=# CREATE OR REPLACE PROCEDURE proc_add( param1 in INTEGER, param2 out INTEGER, param3 in INTEGER)ASBEGIN param2:= param1 + param3;END;/gaussdb=# DECLARE input1 INTEGER:=1; input2 INTEGER:=2; statement VARCHAR2(200); param2 INTEGER;BEGIN --声明调用语句 statement := 'call proc_add(:col_1, :col_2, :col_3)'; --执行语句 EXECUTE IMMEDIATE statement USING IN input1, OUT param2, IN input2; dbe_output.print_line('result is: '||to_char(param2));END;/result is: 3ANONYMOUS BLOCK EXECUTE--删除存储过程。gaussdb=# DROP PROCEDURE proc_add;
  • 语法 语法请参见图1。 图1 call_procedure::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: CALL procedure_name,调用存储过程。 [:placeholder1,:placeholder2,…],存储过程参数占位符列表,占位符名不能使用带引号的数字、字符或字符串。占位符个数与参数个数相同。 USING [IN|OUT|IN OUT] bind_argument,用于指定存放传递给存储过程参数值的变量。bind_argument前的修饰符与对应参数的修饰符一致。 不支持调用带有占位符的重载函数或者存储过程。
  • 场景一:磁盘满后快速定位存储倾斜的表 首先,通过pg_stat_get_last_data_changed_time(oid)函数查询出近期发生过数据变更的表,鉴于表的最后修改时间只在进行IUD操作的CN记录,要查询库内1天(间隔可在函数中调整)内被修改的所有表,可以使用如下封装函数: 1 2 3 4 5 6 7 8 9101112131415161718192021 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();
  • 场景二:常规数据倾斜巡检 在库中表个数少于1W的场景,直接使用倾斜视图查询当前库内所有表的数据倾斜情况。 1 SELECT * FROM pgxc_get_table_skewness ORDER BY totalsize DESC; 在库中表个数非常多(至少大于1W)的场景,因PGXC_GET_TABLE_SKEWNESS涉及全库查并计算非常全面的倾斜字段,所以可能会花费比较长的时间(小时级),建议参考PGXC_GET_TABLE_SKEWNESS视图定义,直接使用table_distribution()函数自定义输出,减少输出列进行计算优化,例如: 123456 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;
  • 示例 gaussdb=# DROP TABLE IF EXISTS customers;NOTICE: table "customers" does not exist, skippingDROP TABLEgaussdb=# CREATE TABLE customers(id int,name varchar);CREATE TABLEgaussdb=# INSERT INTO customers VALUES(1,'ab');gaussdb=# DECLARE my_id integer;BEGIN select id into my_id from customers limit 1; -- 赋值END;/ANONYMOUS BLOCK EXECUTEgaussdb=# DECLARE type id_list is varray(6) of customers.id%type; id_arr id_list;BEGIN select id bulk collect into id_arr from customers order by id DESC limit 20; -- 批量赋值END;/ANONYMOUS BLOCK EXECUTE BULK COLLECT INTO 只支持批量赋值给数组或集合。数组类型合理使用LIMIT字段避免操作过量数据导致性能下降。 对于数组变量,小括号"()"将优先识别为下标,因此对于带括号的表达式,不支持写在数组变量后面。如对于select (1+3) into va(5),不支持写为select into va(5) (1+3)或select into va[5] (1+3)。 BULK COLLECT INTO 只支持在ORA兼容性数据库下使用。
  • 变量赋值示例 1 2 3 4 5 6 7 8 910111213 gaussdb=# DECLARE emp_id INTEGER := 7788;--赋值BEGIN emp_id := 5;--赋值 DBE_OUTPUT.PRINT_LINE(emp_id); emp_id := 5*7784; DBE_OUTPUT.PRINT_LINE(emp_id);END;/--结果如下:538920ANONYMOUS BLOCK EXECUTE
  • 示例 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738 gaussdb=# CREATE OR REPLACE PROCEDURE proc_case_branch(pi_result in integer, pi_return out integer)AS BEGIN CASE pi_result WHEN 1 THEN pi_return := 111; WHEN 2 THEN pi_return := 222; WHEN 3 THEN pi_return := 333; WHEN 6 THEN pi_return := 444; WHEN 7 THEN pi_return := 555; WHEN 8 THEN pi_return := 666; WHEN 9 THEN pi_return := 777; WHEN 10 THEN pi_return := 888; ELSE pi_return := 999; END CASE; raise info 'pi_return : %',pi_return ; END; /CREATE PROCEDUREgaussdb=# CALL proc_case_branch(3,0);INFO: pi_return : 333 pi_return ----------- 333(1 row)--删除存储过程gaussdb=# DROP PROCEDURE proc_case_branch;DROP PROCEDURE
  • 示例 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627 --删除EMP表中某部门的所有员工,如果该部门中已没有员工,则在DEPT表中删除该部门。CREATE TABLE hr.staffs_t1 AS TABLE hr.staffs;CREATE TABLE hr.sections_t1 AS TABLE hr.sections;CREATE OR REPLACE PROCEDURE proc_cursor3() AS DECLARE V_DEPTNO NUMBER(4) := 100; BEGIN DELETE FROM hr.staffs WHERE section_ID = V_DEPTNO; --根据游标状态做进一步处理 IF SQL%NOTFOUND THEN DELETE FROM hr.sections_t1 WHERE section_ID = V_DEPTNO; END IF; END;/CALL proc_cursor3(); proc_cursor3 --------------(1 row)--删除存储过程和临时表DROP PROCEDURE proc_cursor3;DROP TABLE hr.staffs_t1;DROP TABLE hr.sections_t1;
  • 示例 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142 --创建表student1。gaussdb=# CREATE TABLE student1gaussdb=# (gaussdb=# stuno int,gaussdb=# classno int gaussdb=# )gaussdb=# DISTRIBUTE BY hash(stuno);--插入数据。gaussdb=# INSERT INTO student1 VALUES(1,1);gaussdb=# INSERT INTO student1 VALUES(2,2);gaussdb=# INSERT INTO student1 VALUES(3,3);--查看数据。gaussdb=# SELECT * FROM student1;--直接更新所有记录的值。gaussdb=# UPDATE student1 SET classno = classno*2;--查看数据。gaussdb=# SELECT * FROM student1;--删除表。gaussdb=# DROP TABLE student1;--WHERE CURRENT OF cursor_name用例gaussdb=# CREATE TABLE t1(c1 int, c2 varchar2); -- 创建表gaussdb=# INSERT INTO t1 VALUES(generate_series(1,1000),'abcd'); -- 插入数据gaussdb=# DECLAREgaussdb-# CURSOR cur1 IS SELECT * FROM t1 WHERE c1 = 1 FOR UPDATE;gaussdb-# va t1%rowtype;gaussdb-# BEGINgaussdb$# OPEN cur1;gaussdb$# FETCH cur1 INTO va;gaussdb$# SET t1 SET c2 = c2 || c2 WHERE CURRENT OF cur1; -- 使用WHERE CURRENT OF cursor_name更新数据gaussdb$# CLOSE cur1;gaussdb$# COMMIT;gaussdb$# END;gaussdb$# /gaussdb=# SELECT * FROM t1 WHERE c1 = 1; -- 查询数据
  • 注意事项 表的所有者、拥有表UPDATE权限的用户或拥有UPDATE ANY TABLE权限的用户,有权更新表中的数据,系统管理员默认拥有此权限。 UPDATE...... LIMIT row_count 仅支持执行计划下推的部分场景(不支持复制表),前置条件是过滤条件需要包含等值分布列,且过滤条件相对简单,避免使用强制类型转换。如果执行失败,请简化过滤条件。 对expression或condition条件里涉及到的任何表要有SELECT权限。 不允许对表的分布列(distribute column)进行修改。 对于子查询是stream计划的UPDATE语句,不支持并发更新同一行。 不支持用户通过update系统表的方式将数据库编码更改为GB18030_2022字符集或将GB18030_2022字符集数据库更改为其他字符编码,进行更改数据库字符编码的操作会导致存量数据和部分操作异常。若需更改数据库的字符集编码,应当遵循切库流程,进行相关的数据迁移操作。
  • 语法格式 1 2 3 4 5 6 7 8 9101112131415161718 [ 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 | WHERE CURRENT OF cursor_name ] [ ORDER BY {expression [ [ ASC | DESC | USING operator ] [ LIMIT row_count ] [ 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 | WHERE CURRENT OF cursor_name ][ GROUP BY grouping_element [, ...] ][ HAVING condition [, ...] ][ ORDER BY {expression [ [ ASC | DESC | USING operator ] | nlssort_expression_clause ] [ NULLS { FIRST | LAST } ]} [, ...] ][ LIMIT { [offset,] count | ALL } ]
  • 参数说明 WITH [ RECURSIVE ] with_query [, ...] 用于声明一个或多个可以在主查询中通过名称引用的子查询,相当于临时表。这种子查询语句结构称为CTE(Common Table Expression)结构,应用这种结构时,执行计划中将存在CTE SCAN的内容。 如果声明了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 要更新的表名,可以使用模式修饰。 取值范围:已存在的表名称。 支持使用DATABASE LINK方式对远端表进行操作,使用方式详情请见DATABASE LINK。 alias 目标表的别名。 取值范围:字符串,符合标识符命名规范。 column_name 要修改的字段名。 支持使用目标表的别名加字段名来引用这个字段。例如: UPDATE foo AS f SET f.col_name = namecol'; 取值范围:已存在的字段名。 expression 赋给字段的值或表达式。 DEFAULT 用对应字段的缺省值填充该字段。 如果没有缺省值,则为NULL。 sub_query 子查询。 使用同一数据库里其他表的信息来更新一个表可以使用子查询的方法。其中SELECT子句具体介绍请参考SELECT。 在UPDATE单列时,支持使用ORDER BY子句与LIMIT子句;而在UPDATE多列时,则不支持使用ORDER BY子句与LIMIT子句。 对于UPDATE t1 SET (c1,c2) = (SELECT c1, c2 FROM t2 ...)形式的UPDATE语句,在执行计划中,对于每一个字段,会生成一个子计划。当更新字段数较多时,子计划数量较多,对性能影响较大。 from_list 一个表的表达式列表,允许在WHERE条件里使用其他表的字段。与在一个SELECT语句的FROM子句里声明表列表类似。 目标表不能出现在from_list里,除非在使用一个自连接(此时它必须以from_list的别名出现)。 condition 一个返回Boolean类型结果的表达式。只有这个表达式返回true的行才会被更新。不建议使用int等数值类型作为condition,因为int等数值类型可以隐式转换为Boolean值(非0值隐式转换为true,0转换为false),可能导致非预期的结果。 WHERE CURRENT OF cursor_name 当cursor指向表的某一行时,可以使用此语法更新cursor当前指向的行。 cursor_name:指定游标的名称。 MYSQL兼容模式的数据库不支持使用此语法。 此语法仅支持普通表,不支持分区表,不支持Hash Bucket表。 仅支持在存储过程中使用。 不支持与其他WHERE条件组合使用。 不支持与WITH、USING、ORDER BY、FROM组合使用。 CURSOR对应的SELECT语句必须声明为FOR UPDATE。 CURSOR对应的SELECT语句仅支持单表,不支持LIMIT/OFFSET,不支持带有子查询、子链接。 存储过程中声明为FOR UPDATE的CURSOR,在COMMIT/ROLLBACK后,将无法再次使用。 若CURSOR指向的行已经不存在,在ORA兼容性模式下将报错指定的行不存在(仅UPDATE时报错,DELETE不报错),其他兼容模式下不报错。 复制表使用此语法时,不支持下推,必须有主键。 ORDER BY子句 关键字详见SELECT章节介绍。 LIMIT子句 关键字详见SELECT章节介绍。 output_expression 在所有需要更新的行都被更新之后,UPDATE命令用于计算返回值的表达式。 取值范围:使用任何TABLE以及FROM中列出的表的字段。*表示返回所有字段。 output_name 字段的返回名称。
  • 示例 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738 gaussdb=# DROP TABLE t1;gaussdb=# CREATE TABLE t1(a int);gaussdb=# INSERT INTO t1 VALUES(1),(10);--RETURN NEXTgaussdb=# CREATE OR REPLACE FUNCTION fun_for_return_next() RETURNS SETOF t1 AS $$DECLARE r t1%ROWTYPE;BEGIN FOR r IN select * from t1 LOOP RETURN NEXT r; END LOOP; RETURN;END;$$ LANGUAGE plpgsql;gaussdb=# call fun_for_return_next(); a--- 1 10(2 rows)-- RETURN QUERYgaussdb=# CREATE OR REPLACE FUNCTION fun_for_return_query() RETURNS SETOF t1 AS $$DECLARE r t1%ROWTYPE;BEGIN RETURN QUERY select * from t1;END;$$language plpgsql;gaussdb=# call fun_for_return_query(); a--- 1 10(2 rows)
  • 语法 创建函数时需要指定返回值SETOF datatype。 return_next_clause::= return_query_clause::= 对以上语法的解释如下: 当需要函数返回一个集合时,使用RETURN NEXT或者RETURN QUERY向结果集追加结果,然后继续执行函数的下一条语句。随着后续的RETURN NEXT或RETURN QUERY命令的执行,结果集中会有多个结果。函数执行完成后会一起返回所有结果。 RETURN NEXT可用于标量和复合数据类型。 RETURN QUERY有一种变体RETURN QUERY EXECUTE,后面还可以增加动态查询,通过USING向查询插入参数。
  • 示例 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839 --创建表。gaussdb=# CREATE TABLE sections_t1( section NUMBER(4) , section_name VARCHAR2(30), manager_id NUMBER(6), place_id NUMBER(4) )DISTRIBUTE BY hash(manager_id);--声明变量。gaussdb=# DECLARE section NUMBER(4) := 280; section_name VARCHAR2(30) := 'Info support'; manager_id NUMBER(6) := 103; place_id NUMBER(4) := 1400; new_colname VARCHAR2(10) := 'sec_name';BEGIN --执行查询。 EXECUTE IMMEDIATE 'insert into sections_t1 values(:1, :2, :3, :4)' USING section, section_name, manager_id,place_id; --执行查询(重复占位符)。 EXECUTE IMMEDIATE 'insert into sections_t1 values(:1, :2, :3, :1)' USING section, section_name, manager_id; --执行ALTER语句(建议采用“||”拼接数据库对象构造DDL语句)。 EXECUTE IMMEDIATE 'alter table sections_t1 rename section_name to ' || new_colname;END; /--查询数据。gaussdb=# SELECT * FROM sections_t1; section | sec_name | manager_id | place_id ---------+--------------+------------+---------- 280 | Info support | 103 | 1400 280 | Info support | 103 | 280(2 rows)--删除表。gaussdb=# DROP TABLE sections_t1;
  • 语法 语法请参见图1。 图1 noselect::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: USING IN bind_argument用于指定存放传递给动态SQL值的变量,在dynamic_noselect_string中存在占位符时使用,即动态SQL语句执行时,bind_argument将替换相对应的占位符。要注意的是,bind_argument只能是值、变量或表达式,不能是表名、列名、数据类型等数据库对象。如果存储过程需要通过声明参数传递数据库对象来构造动态SQL语句(常见于执行DDL语句时),建议采用连接运算符“||”拼接dynamic_select_clause。另外,动态语句允许出现重复的占位符,相同占位符只能与唯一一个bind_argument按位置一一对应。当设置guc参数behavior_compat_options值为dynamic_sql_compat时,会按照占位符的顺序依次匹配USING子句bind_argument,重复的占位符不会再识别为同一个占位符(占位符名不能使用带引号的数字、字符或字符串)。
  • 示例 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 gaussdb=# DROP SCHEMA IF EXISTS hr CASCADE;gaussdb=# CREATE SCHEMA hr;gaussdb=# SET CURRENT_SCHEMA = hr;gaussdb=# CREATE TABLE staffs ( staff_id NUMBER, first_name VARCHAR2, salary NUMBER);gaussdb=# INSERT INTO staffs VALUES (200, 'mike', 5800);gaussdb=# INSERT INTO staffs VALUES (201, 'lily', 3000);gaussdb=# INSERT INTO staffs VALUES (202, 'john', 4400);--创建存储过程dynamic_proc。gaussdb=# CREATE OR REPLACE PROCEDURE dynamic_procAS staff_id NUMBER(6) := 200; first_name VARCHAR2(20); salary NUMBER(8,2);BEGIN --执行匿名块 。 EXECUTE IMMEDIATE 'begin select first_name, salary into :first_name, :salary from hr.staffs where staff_id= :dno; end;' USING OUT first_name, OUT salary, IN staff_id; dbe_output.print_line(first_name|| ' ' || salary);END;/--调用存储过程。gaussdb=# CALL dynamic_proc();mike 5800.00 dynamic_proc --------------(1 row)--删除存储过程。gaussdb=# DROP PROCEDURE dynamic_proc;--开启dynamic_sql_check时报错示例。gaussdb=# SET behavior_compat_options = 'dynamic_sql_check';SETgaussdb=# CREATE OR REPLACE PROCEDURE test_proc_exception001(a out integer, b inout integer, c integer) as BEGIN a := 1; begin b := 1/0; end; EXCEPTION WHEN others THEN b := 2; END;/CREATE PROCEDUREgaussdb=# DECLARE a integer := 1; c integer; BEGIN execute immediate 'begin test_proc_exception001(:1,:2,:1); end;' using in out a, out c, a; END;/ERROR: argnum not match in Dynamic SQL, using args num : 3 , actual sql args num : 2CONTEXT: PL/pgSQL function inline_code_block line 4 at EXECUTE statement--修改同名占位符。gaussdb=# DECLARE a integer := 1; c integer; BEGIN execute immediate 'begin test_proc_exception001(:1,:2,:3); end;' using in out a, out c, a; END;/ANONYMOUS BLOCK EXECUTEgaussdb=# DROP PROCEDURE test_proc_exception001;DROP PROCEDUREgaussdb=# reset behavior_compat_options;
  • 语法 语法请参见图1。 图1 call_anonymous_block::= using_clause子句的语法参见图2。 图2 using_clause::= 对以上语法格式的解释如下: 匿名块程序实施部分,以BEGIN语句开始,以END语句停顿,以一个分号结束。 USING [IN|OUT|IN OUT] bind_argument,用于指定存放传递给存储过程参数值的变量。bind_argument前的修饰符与对应参数的修饰符一致。 匿名块中间的输入输出参数使用占位符来指明,要求占位符个数与参数个数相同(占位符名不能使用带引号的数字、字符或字符串),并且占位符所对应参数的顺序和USING中参数的顺序一致。 目前GaussDB在动态语句调用匿名块时,EXCEPTION语句中暂不支持使用占位符进行输入输出参数的传递。 不支持调用带有占位符的重载函数。 不支持绑定参数时使用PERFORM关键字调用存储过程。 不支持同一条语句同时使用匿名块内声明的变量和绑定参数。 不支持匿名块中SELECT INTO语句调用含有出参的FUNCTION/PROCEDURE时,绑定出参。 仅支持匿名块中调用SQL语句以及带有out/inout参数的存储过程绑定参数,其余绑定参数场景皆不支持。例如:匿名块中使用表达式以及cursor等、匿名块中嵌套调用动态语句。 打开dynamic_sql_check参数时,占位符个数与参数个数一致时使用同名占位符作为匿名块参数会报错,需修改为不同名参数。
共99354条