#UPDATE
# 通用描述
UPDATE用于修改数据库的表中的数据,包括HEAP表、TAC表和LSC表,其中,对LSC表的UPDATE存在如下约束限制:
- 只能修改LSC表可变数据区的MCOL数据,已转换为SCOL结构的稳态数据不允许修改。
- 不能对LSC表执行跨分区更新。
- 不能对AC执行UPDATE操作。
在UPDATE的事务(Transaction)被提交(Commit)之前,其他会话无法查询到这些被修改的数据。在YashanDB里,可以通过打开自动提交(SET AUTOCOMMIT ON)的开关,这样其他会话将可以及时查询到这些数据。
对于被子表定义了外键约束的父表,如果要被更新的列字段为该外键项且其数据值已在子表中存在,则无法更新该父表中的此项数据。
# 语句定义
update::=
dml_table_expression_clause::=
# hint
该语句用于提出给定的方案到优化器(Optimizer ),使其按照此方案生成语句的执行计划。查看hint说明。
# dml_table_expression_clause
该语句用于指定要更新数据的对象,即表或表分区,可对其指定一个别名。
对于分区表,如未显式指定分区对象,由系统根据分区项字段的值判断要更新的表分区。在显式指定且表未被定义为ENABLE ROW MOVEMENT时:
- 当分区表类型为RANGE时,如更新该表的分区项字段,请注意不要超出其所在分区的界值,否则会更新失败并提示错误。
- 当分区表类型为LIST时,如更新该表的分区项字段,请注意数据值在其所在分区的列表项中,否则会更新失败并提示错误。
对于分布式部署中的分布表,不允许修改其分布键字段的值。
示例1
--sales_info_range为一张范围分区表,p_sales_info_range_1(VALUES LESS THAN('2011'))、p_sales_info_range_2(VALUES LESS THAN('2021'))和p_sales_info_range_3(VALUES LESS THAN('2031'))三个分区
SELECT * FROM sales_info_range PARTITION (p_sales_info_range_1);
YEAR MONTH BRANCH PRODUCT QUANTITY AMOUNT SALSPERSON
----- ----- ------ --------- --------------------- --------------------- -------------
2001 01 0201 11001 30 500 0201010011
2000 12 0102 11001 20 300
--单机部署中,要更新数据的此行记录位于sales_info_range 表的p_sales_info_range_1分区,其界值为'2011',对year字段的超出界值更新将会失败
UPDATE sales_info_range PARTITION (p_sales_info_range_1) SET year='2023' WHERE year='2001';
YAS-02209 ROW MOVEMENT is not enabled
--分布式部署中,对分布表的分布键执行update将失败
UPDATE sales_info_range PARTITION (p_sales_info_range_1) SET year='2023' WHERE year='2001';
YAS-04510 cannot update distributed keys for sharded table
示例2(只针对单机部署)
--sales_info_list为一张列表分区表,已有p_sales_info_list_1(VALUES('2018','2019'))、p_sales_info_list_2(VALUES('2021'))两个分区
--未指定分区时,按分区项判断更新值不在当前分区列表中,更新数据失败
UPDATE sales_info_list SET year='2021' WHERE year='2018';
YAS-02209 ROW MOVEMENT is not enabled
--指定分区时,按分区项判断其原值和更新值均在指定分区,更新数据成功
UPDATE sales_info_list PARTITION (p_sales_info_list_1) SET year='2019' WHERE year='2018';
SELECT * FROM sales_info_list PARTITION (p_sales_info_list_1);
YEAR MONTH BRANCH PRODUCT QUANTITY AMOUNT SALSPERSON
----- ----- ------ --------- --------------------- --------------------- -------------
2019 10 0101 11001 20 300
# partition_extension_clause
与INSERT语句中partition_extension_clause的描述一致。
# update_set_clause
该语句用于指定要更新数据的列字段,并对其赋值。
YashanDB支持通过两种方式更新多个列字段:
- UPDATE table_name SET column = value, column = value;
- UPDATE table_name SET (column,...,column) = (value,...value);
YashanDB支持按如下语句对列字段赋值:
- expr表达式
- 子查询(只针对单机部署,分布式部署不适用)
- DEFAULT
对于UDT列字段,通过对象初始化方法赋值,详见用户自定义类型中描述。
当上述语句的结果与列字段定义的数据类型不一致时,系统会先进行数据类型转换,转换失败则返回错误。
使用方式二更新多个列字段有如下约束限制:
- 不支持使用UDT。
- 括号内指定的列字段需位于同一张表,否则返回错误。
- 除对所有指定列字段均赋值为DEFAULT情况外,其他情况下值的数量需与列字段数量相同。
- value中不允许同时出现子查询和表达式。
示例
--在area表中插入数据
INSERT INTO area VALUES ('09','Other','Shanghai1');
--更新多个列字段(方式一)
UPDATE area SET area_name=23*67,DHQ='Shanghai1' WHERE area_no='09';
--result
SELECT * FROM area WHERE area_no='09';
AREA_NO AREA_NAME DHQ
------- -------------- ------------
09 1541 Shanghai1
--更新多个列字段(方式二)
UPDATE area SET (area_name,DHQ) = ('华西','Shanxi');
其中,当使用子查询对列字段赋值时,更新的列字段须与子查询返回的列项必须按顺序一一对应,且子查询的返回结果不能为多条。如子查询无返回结果,将以NULL值返回,此时如对应的列存在非空约束,则更新数据失败。
示例(只针对单机部署)
--根据上面示例在area表插入'09'区域记录后,将DHQ更新为'Shanghai2'
UPDATE area SET DHQ='Shanghai2' WHERE area_no='09';
--在area表中未检索到DHQ='Shanghai1'的记录,以NULL值对DHQ字段进行更新触发非空约束错误
UPDATE area SET DHQ = (SELECT a.DHQ FROM area a WHERE a.DHQ='Shanghai1') WHERE area_no='09';
YAS-04006 can not insert null value to column DHQ
--子查询返回多行记录,更新提示错误
UPDATE area SET DHQ = (SELECT a.DHQ FROM area a WHERE a.DHQ LIKE 'Shanghai%') WHERE area_no='09';
[1:23]YAS-04402 query expression return multiple rows
当使用DEFAULT对列字段赋值时,如对应的列上已定义了DEFAULT值,则更新的数据为该DEFAULT值,否则为NULL,基于这个规则,如对应的列存在非空约束,则更新数据失败。
示例
--area表上的DHQ字段已定义了DEFAULT值'ShenZhen',则按此值更新数据成功
UPDATE area SET DHQ=DEFAULT WHERE area_no='01';
--branches表上的BRANCH_NAME字段非空且无DEFAULT值,则按NULL值更新数据失败
UPDATE branches SET branch_name=DEFAULT WHERE branch_no='0201';
YAS-04006 can not insert null value to column BRANCH_NAME
# where condition
该语句用于指定condition,按此条件过滤出的记录行被执行更新操作。可省略,则表示更新表的所有行。