Skip to content

适用虚谷数据库版本

v12.9



适用虚谷数据库版本

v12.9


UPDATE

📄字数 3.7K
👁️阅读量 加载中...

一、概述

1.1 UPDATE 定义

UPDATE是SQL中的数据操作语言(DML)语句之一,用于修改表或视图中现有数据的值。其主要功能包括:

  • 修改表中已存在的一条或多条记录
  • 基于指定条件选择性更新数据
  • 批量更新大量数据记录
  • 支持多列同时更新
  • 与其他表关联进行跨表更新

1.2 UPDATE 约束条件

UPDATE 语句在执行时需要满足数据库中的多种约束条件,以确保数据的完整性和一致性。UPDATE 操作需要满足的主要约束条件包括:

  1. 主键约束:
    • 不能将主键列的值更新为NULL。
    • 不能更新为主键列中已存在的值(必须保持唯一性)。
  2. 唯一约束:如果更新唯一约束列的值,新值不能与表中其他行的该列值重复。
  3. 外键约束:
    • 如果更新的是外键列,新值必须在被引用表的主键列或唯一约束列中存在。
    • 如果被引用的表的记录被更新(例如级联更新),则根据定义的外键动作(ON UPDATE CASCADE, SET NULL, SET DEFAULT, NO ACTION等)进行相应处理。
  4. 检查约束:更新的值必须满足表中定义的CHECK条件。
  5. 非空约束:如果列有NOT NULL约束,则不能将该列更新为NULL。

1.3 权限要求

  1. 用户对目标表或视图具有 UPDATE 权限。
  2. 如果利用查询结果进行更新,则用户需要对目标表或视图具有 SELECT 权限。

二、语法格式

三、参数解释

  • base_table_refs:更新的表或视图名列表,前面可加上相应的模式名,支持多表更新
    • base_table_ref:更新的表或视图名,前面可加上相应的模式名
      • relation_expr:插入对象,可以是表或视图,详细说明参见 relation_expr
        • (schema_name '.')?:可选的模式名
        • table_name | view_name:表名或视图名
        • @link_name:指定远程数据库对象,详细说明参见 link_name
        • opt_parti_clip_clause:分区子句
          • PARTITION:用于指定要更新的表的一级分区
          • SUBPARTITION:用于指定要更新的表的二级分区
          • name_list:分区名列表,可以指定一个或多个分区名,指定多个时,使用英文逗号分隔
      • alias_clause:表名或表的别名,该部分为可选项
  • update_filter_clausefrom 子句指定数据来源,where 子句过滤待更新表或视图的行
    • update_target_list:更新的目标列表,可以指定一个或多个目标名,指定多个时,使用英文逗号分隔
      • update_target_el: 更新目标元素
        • ColumnName:列名。后面不跟其他表达式时,等同于更新为 DEFAULT
        • bool_expr:布尔表达式,使用此项时,要求被更新的列为布尔类型
        • b_expr:要修改成的值
        • DEFAULT:默认值,如果列没有默认值,则不会进行更新
        • ident_arr '=' b_expr:数组类型的更新方式,详细说明参见 数组的更新
    • opt_from_clausefrom 子句,允许其他表中的列出现在 WHERE 子句和update_target_list表达式中,详细说明参见 FROM子句
      • form_list:数据的来源列表,,可以指定一个或多个数据来源,指定多个时,使用英文逗号分隔
    • update_where_clause:更新满足条件的行
      • opt_where_clausewhere 子句,详细说明参见 WHERE子句
      • WHERE CURRENT OF cursor_name :用于在PL/SQL中通过游标更新当前行,其中 cursor_name 为游标变量的名字
  • update_select_clause:利用 select 子句的查询结果更新表或视图的行。
    • update_target_list:更新的目标列表,可以指定一个或多个目标名,指定多个时,使用英文逗号分隔
    • select_with_parens:查询子句,查询结果的列数需要与 update_target_list 指定的列数相同。查询子句详细说明参见SELECT
  • opt_returning:可选的关键词,用于把更新后的结果输出至指定的变量或数据结构
    • target_list:变量或数据结构值列表,可以指定一个或多个变量或数据结构,指定多个时,使用英文逗号分隔
  • opt_bulk:可选关键词,允许一次性加载查询结果集到变量中,提高大规模查询下的性能
  • opt_into_list:可选的关键词,允许将结果集赋值给某些变量
    • ident_list:变量名列表,可以指定一个或多个变量名,指定多个时,使用英文逗号分隔
      • IDENT:变量名

提示

  1. WHERE CURRENT OF只能用于游标循环中,所使用的游标必须声明为FOR UPDATE,这是为了在打开游标时锁定行,防止被其他事务修改
  2. WHERE CURRENT OF只能用于UPDATEDELETE,且不能和普通WHERE混合使用
  3. 在PL/SQL中,RETURNING返回的结果必须匹配对应的字段列表
  4. UPDATE语句不支持 order by 子句和 limit 子句

四、示例

sql
-- 准备表和数据
SQL> CREATE TABLE tab_update1(c1 INT, c2 CHAR(20), C3 INT DEFAULT 100);
SQL> CREATE TABLE tab_update2(c1 INT, c2 CHAR(20), C3 INT DEFAULT 100);
SQL> INSERT INTO tab_update1 VALUES(1, 'c2_1', 101);
SQL> INSERT INTO tab_update1 VALUES(2, 'c2_2', 102);
SQL> INSERT INTO tab_update1 VALUES(3, 'c2_3', 103);

-- 更新结果为常值
SQL> UPDATE tab_update1 SET c2 = 'new c2', c3 = DEFAULT WHERE c1 = 1;
SQL> SELECT * FROM tab_update1;

+----+--------+-----+
| C1 |   C2   | C3  |
+----+--------+-----+
| 1  | new c2 | 100 |
| 2  | c2_2   | 102 |
| 3  | c2_3   | 103 |
+----+--------+-----+

-- 更新结果为子查询
SQL> UPDATE tab_update1 SET (c2, c3) = (SELECT MAX(c2), MIN(c3) + 10 FROM tab_update1) WHERE c1 = 2;
SQL> SELECT * FROM tab_update1;

+----+--------+-----+
| C1 |   C2   | C3  |
+----+--------+-----+
| 1  | new c2 | 100 |
| 2  | new c2 | 110 |
| 3  | c2_3   | 103 |
+----+--------+-----+

-- 更新时将结果 RETURNING
SQL> DECLARE
    TYPE type_table_1 IS TABLE OF tab_update1%ROWTYPE; -- UDT 类 型 : tab_update1 行类型的嵌套表
    var_t1 TYPE_TABLE_1; -- UDT 类型变量, 用来保存游标中查询的数据
    TYPE type_table_int IS TABLE OF tab_update1.c2%TYPE; -- UDT 类 型 : INT 类型的嵌套表
    var_int TYPE_TABLE_INT; -- UDT 类型变量, 用来保存 RETURNING 的值
    CURSOR cur IS SELECT * FROM tab_update1 ;
BEGIN
    OPEN cur ;
    FETCH cur BULK COLLECT INTO var_t1 ;
    UPDATE tab_update1 SET c2 = var_t1(1).c2, c3 = c3 + 100 RETURNING c1 BULK COLLECT INTO var_int ;
    CLOSE cur ;
    -- 如果需要,可把 RETUNING 的数据输出至屏幕中
    FOR i IN 1..var_int.COUNT() LOOP
        SEND_MSG(var_int(i)) ;
    END LOOP ;
END ;
/
1
2
3

Execute successful.
Use time:0 ms.