UPDATE
功能描述
更新表中的数据,UPDATE对满足条件的所有行中指定的字段值进行修改。WHERE子句表示声明条件;SET子句中指定的字段将会被修改,没有出现的字段则保持原有的字段值。
注意事项
- 表的所有者、拥有表UPDATE权限的用户、拥有UPDATE ANY TABLE权限的用户,皆有权限更新表中的数据,当三权分立开关关闭时,系统管理员默认拥有此权限。
- UPDATE...... LIMIT row_count 仅支持执行计划下推的部分场景(不支持复制表),前置条件要求过滤条件包含等值分布列且过滤条件相对简单,避免出现强制类型转换的情况。如果执行失败,请简化过滤条件。
- 对expression或condition条件里涉及到的任何表需要有SELECT权限。、
- 仅当表属性enable_update_distkey设置为on,且在约束条件下时,支持更新(UPDATE)分布列的操作。否则,分布列不支持更新(UPDATE)操作。
支持更新(UPDATE)分布列操作的约束如下:
- 仅当相应表属性enable_update_distkey设置为on时才支持更新分布列;
- 不支持将UPDATE语句下推DN执行,直接生成PGXC计划,不会根据更新分布列前后值而对计划做改变;
- 不支持带有行级UPDATE TRIGGER的表,否则会执行失败,报错进行提示。对行级INSERT/DELETE TRIGGER不生效,update statement级TRIGGER正常执行;
- 不支持并发更新同一行,先获取锁的执行,DN上后获取锁的按照GUC参数concurrent_dml_mode设置情况进行不同的行为(返回0或报错)。如果报错,则可能存在两种情况:(1)报错提示信息为update distribute column conflict;(2)当获取锁时间超过阈值时,报错提示信息为锁超时。
- 不支持带有全局二级索引(GSI)的表,否则会执行报错;
- 只支持HASH分布,不支持LIST/RANGE分布表,否则会执行报错;
- 不支持MERGE INTO和UPSERT更新分布列的行为,否则会执行报错;
- 不支持gtm_free,否则会执行报错;
- 不支持带有关联表的语句,否则会执行报错;
- 不支持UPDATE + LIMIT,否则会执行报错。
- 对于子查询是STREAM计划的UPDATE语句,不支持并发更新同一行。
- 不支持用户通过UPDATE系统表的方式对数据库字符编码进行修改,该操作会导致存在存量数据或其他部分操作异常的情况。如需更改数据库的字符集编码,应当遵循切库流程,进行相关的数据迁移操作。
语法格式
UPDATE [/*+ plan_hint */] [IGNORE] [ ONLY ] {table_name [ partition_clause ] | view_name} [ * ] [ [ AS ] alias ]
SET {column_name = { expression | DEFAULT }
}[, ...]
[ WHERE condition ]
[ORDER BY {col_name | expression | position}
[ASC | DESC][ NULLS { FIRST | LAST } ], ...]
[ LIMIT { count } ]
[ RETURNING {* | {output_expression [ [ AS ] output_name ] }[, ...]} ];
参数说明
- plan_hint
以/*+ */的形式在UPDATE关键字后,用于对UPDATE对应的语句块生成的计划进行hint调优。每条语句中只有第一个/*+ plan_hint */注释块会作为hint生效,里面可以写多条hint。
- IGNORE
UPDATE语句使用IGNORE关键字时,可将部分ERROR级别的错误降级为WARNING级别,并根据不同的错误场景将无效值调整为最接近的值。GaussDB支持错误降级的场景如下:
- 破坏NOT NULL约束
- 唯一键冲突
- 插入的值没有找到对应的分区
- 指定分区插入时,插入的数据与指定分区不匹配
- 子查询返回多行
- sql_mode为宽松模式的场景
- table_name
要更新的表名,可以使用模式修饰。如果在表名前指定了ONLY,只会更新表中匹配的行。如果未指定,任何从该表继承得到的表中的匹配行也会被更新。目前ONLY和增加*选项保留语法,功能不支持
取值范围:已存在的表名称。
- partition_clause
指定分区更新操作
PARTITION { ( { partition_name | subpartition_name } [, ...] ) | FOR ( partition_value [, ...] ) }
关键字请参见SELECT。
PARTITION指定多个分区名时,可以存在相同的分区名,最终分区范围取其并集。
- view_name
要更新的目标视图。
对视图的更新,有如下约束:
- 只有直接引用基表用户列的列可进行UPDATE操作。
- 视图必须至少包含一个可更新列,关于可更新列请参见CREATE VIEW。
- 不支持在顶层包含DISTINCT、GROUP BY、HAVING、LIMIT、OFFSET子句的视图。
- 不支持在顶层包含集合运算(UNION以及EXCEPT)的视图。
- 不支持目标列表中包含聚集函数、窗口函数、返回集合函数(array_agg、json_agg、generate_series等)的视图。
- 视图中支持的表类型包括普通表、临时表、全局临时表、分区表、ustore表、astore表。
- 多表连接视图中一次只能更新一张基表。
- 连接视图只能更新保留键表。关于保留键表请参见CREATE VIEW。
- 不支持更新系统视图。
- alias
目标表的别名。
取值范围:字符串,符合标识符说明。
- table_list
一个表的表达式列表,与from_list类似,但可以同时声明目标表和关联表,仅在多表更新语法中使用。
- column_name
要修改的字段名。
支持使用目标表的别名加字段名来引用这个字段。例如:UPDATE foo AS f SET f.col_name = 'namecol'。
支持使用库名.别名或库名.表名加字段名来引用这个字段。例如:UPDATE foo AS f SET public.f.col_name = 'namecol'。
取值范围:已存在的字段名。
- expression
赋给字段的值或表达式。
- DEFAULT
用对应字段的缺省值填充该字段。
如果没有缺省值,则为NULL。
- from_list
一个表的表达式列表,允许在WHERE条件里使用其他表的字段。与在一个SELECT语句的FROM子句里声明表列表类似。
目标表不能出现在from_list里,除非在使用一个自连接(此时它必须以from_list的别名出现)。
- condition
一个返回Boolean类型结果的表达式。只有这个表达式返回true的行才会被更新。不建议使用int等数值类型作为condition,因为int等数值类型可以隐式转换为bool值(非0值隐式转换为true,0转换为false),可能导致非预期的结果。
- ORDER BY
关键字详见SELECT章节介绍。
- LIMIT
关键字详见SELECT章节介绍。
- RETURNING
返回实际插入的行,RETURNING列表的语法与SELECT的输出列表一致。
示例
- 修改表中所有数据。
--创建tbl_test1表并插入数据。 m_db=# CREATE TABLE tbl_test1(id int, info varchar(10)); m_db=# INSERT INTO tbl_test1 VALUES (1, 'A'), (2, 'B'); --查询。 m_db=# SELECT * FROM tbl_test1; id | info ----+------ 1 | A 2 | B (2 rows) --修改tbl_test1表中info列的信息。 m_db=# UPDATE tbl_test1 SET info = 'aa'; --查询tbl_test1表。 m_db=# SELECT * FROM tbl_test1; id | info ----+------ 1 | aa 2 | aa (2 rows)
- 修改表中部分数据。
--修改tbl_test1表中id=2的数据。 m_db=# UPDATE tbl_test1 SET info = 'bb' WHERE id = 2; --查询tbl_test1表。 m_db=# SELECT * FROM tbl_test1; id | info ----+------ 1 | aa 2 | bb (2 rows)
- 修改数据,并返回修改后的数据。
--修改tbl_test1表中id=1的数据,并指定返回info列。 m_db=# UPDATE tbl_test1 SET info = 'ABC' WHERE id = 1; UPDATE 1 --删除tbl_test1表。 m_db=# DROP TABLE tbl_test1;
- 更新视图
--创建SCHEMA。 m_db=# CREATE SCHEMA upd_view; CREATE SCHEMA m_db=# SET CURRENT_SCHEMA = 'upd_view'; SET --创建表并插入数据。 m_db=# CREATE TABLE t1 (x1 int, y1 int); CREATE TABLE m_db=# CREATE TABLE t2 (x2 int PRIMARY KEY, y2 int); NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "t2_pkey" for table "t2" CREATE TABLE m_db=# INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (5, 5); INSERT 0 4 m_db=# INSERT INTO t2 VALUES (1, 1), (2, 2), (3, 3), (5, 5); INSERT 0 4 --创建单表视图。 m_db=# CREATE VIEW v_upd1 AS SELECT * FROM t1; CREATE VIEW --通过视图对t1更新。 m_db=# UPDATE v_upd1 SET y1 = 13 where y1 = 3; UPDATE 1 --创建多表视图。 m_db=# CREATE VIEW vv_upd AS SELECT * FROM t1, t2 WHERE x1 = x2; CREATE VIEW --通过连接视图对t1更新。 m_db=# UPDATE vv_upd SET y1 = 1 WHERE y2 = 1; UPDATE 1 --删除SCHEMA。 m_db=# DROP SCHEMA upd_view; NOTICE: drop cascades to 4 other objects DETAIL: drop cascades to table t1 drop cascades to table t2 drop cascades to view v_upd1 drop cascades to view vv_upd DROP SCHEMA