UPDATE
功能描述
更新表中的数据,UPDATE修改满足条件的所有行中指定的字段值,WHERE子句声明条件,SET子句指定的字段会被修改,没有出现的字段则保持它们的原值。
注意事项
- 表的所有者、拥有表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 9 10 11 12 13 14 15 16 17 18 |
[ 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 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 |
--创建表student1。 gaussdb=# CREATE TABLE student1 gaussdb=# ( 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=# DECLARE gaussdb-# CURSOR cur1 IS SELECT * FROM t1 WHERE c1 = 1 FOR UPDATE; gaussdb-# va t1%rowtype; gaussdb-# BEGIN gaussdb$# 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; -- 查询数据 |