UPDATE 语句
UPDATE 语句更新表,视图或昵称,或指定全查询的底层表,昵称或视图的行中指定列的值。
如果没有为此视图上的更新操作定义 INSTEAD OF 触发器,那么更新视图的行将更新其基本表的行。 如果定义了此类触发器,那么将改为执行该触发器。 使用昵称更新行将更新昵称所引用的数据源对象中的行。
- 已搜索 UPDATE 表单用于更新一行或多行 (可选择由搜索条件确定)。
- 定位 UPDATE 表单用于仅更新一行 (由游标的当前位置确定)。
调用
UPDATE 语句可以嵌入应用程序中,也可以通过使用动态 SQL 语句来发出。 它是可动态准备的可执行语句。
授权
- 对目标表,视图或昵称的 UPDATE 特权
- 对要更新的每个列 (包括 BUSINESS_TIME 时间段 (如果指定了 period-子句) 的列) 的 UPDATE 特权
- 对目标表,视图或昵称的模式的 UPDATEIN 特权
- 对目标表,视图或昵称的 CONTROL 特权
- 包含目标表,视图或昵称的模式上的 DATAACCESS
- DATAACCESS 权限
- SELECT 特权
- 对包含引用的表,视图或昵称的模式的 SELECTIN 特权
- CONTROL 特权
- 包含引用的表,视图或昵称的模式上的 DATAACCESS
- DATAACCESS 权限
- SELECT 特权
- 对包含表,视图或昵称的模式的 SELECTIN 特权
- CONTROL 特权
- 包含表,视图或昵称的模式上的 DATAACCESS
- DATAACCESS 权限
- SELECT 特权
- CONTROL 特权
- 包含该表、视图或昵称的模式的 SELECTIN 特权
- 包含表,视图或昵称的模式上的 DATAACCESS
- DATAACCESS 权限
如果指定的表或视图前面有 ONLY 关键字,那么语句的授权标识所拥有的特权还必须包括对指定表或视图的每个子表或子视图的 SELECT 特权,或者对包含指定表或视图的子表或子视图的模式的 SELECT 特权。
不会针对静态 UPDATE 语句检查 GROUP 特权。
如果更新操作的目标是昵称,那么在数据源上执行该语句之前,不会考虑对该对象的特权。 此时,用于连接到数据源的授权标识必须具有对数据源中的对象执行的操作所需的特权。 可以将语句的授权标识映射到数据源上的其他授权标识。
语法 (searched-update)
- 1 If the period-clause is specified, neither the offset-clause nor the fetch-clause can be specified (SQLSTATE 42601).
- 2 The specified table-reference cannot be an analyze_table-expression (that is, the result of a data mining model) or a data-change-table-reference (that is, the result of a nested UPDATE, DELETE, or INSERT statement) (SQLSTATE 42601).
- 3 If the order-by-clause is specified, either the offset-clause or fetch-clause must also be specified (SQLSTATE 42601).
语法 (positioned-update)
- 1 The number of expressions, NULLs and DEFAULTs must match the number of column names.
- 2 The number of columns in the select list must match the number of column names.
描述
- 表名, 视图名称, 昵称或 (全查询)
- 标识更新操作的对象。 该名称必须标识下列其中一个对象:
- 当前服务器上的目录中描述的表,视图或昵称
- 使用 remote-object-name 指定的远程服务器上的表或视图
如果 table-name 是一个类型表,那么该表的行或其任何正确的子表可由该语句更新。 只能在 WHERE 子句中设置或引用指定表的列。 对于定位 UPDATE ,关联的游标还必须在 FROM 子句中指定相同的表,视图或昵称而不使用 ONLY。
如果更新操作的对象是全查询,那么全查询必须是可更新的,如 CREATE VIEW 语句的描述中的
可更新视图
注释项中所定义。如果更新操作的对象是昵称,那么不得使用 DEFAULT 和 UNASSIGNED 的扩展指示符变量值 (SQLSTATE 22539)。
有关与时态表以及使用视图或 全查询 作为更新操作的目标相关的其他限制,请参阅本主题的 "注释" 部分中的
系统周期时态表的注意事项
和应用程序周期时态表的注意事项
。 - 仅 (table-name)
- 对于类型表, ONLY 关键字指定语句应仅应用于指定表的数据,并且语句不能更新正确子表的行。 对于定位 UPDATE ,关联的游标还必须使用 ONLY 在 FROM 子句中指定表。 如果 table-name 不是类型表,那么 ONLY 关键字对语句没有影响。
- 仅 (view-name)
- 适用于带类型视图, ONLY 关键字指定语句应仅应用于指定视图的数据,语句不能更新正确子视图的行。 对于定位的 UPDATE ,关联的游标还必须使用 ONLY 在 FROM 子句中指定视图。 如果 view-name 不是带类型视图,那么 ONLY 关键字对语句没有影响。
- period-clause
- 指定句点子句应用于更新操作的目标。 如果更新操作的目标是视图,那么以下条件适用于该视图:
- 视图定义的外部全查询的 FROM 子句必须直接或间接包含对应用程序时间段时态表的引用 (SQLSTATE 42724M)。
- 不得为视图定义 INSTEAD OF UPDATE 触发器 (SQLSTATE 428HY)。
- 对于部分 business_time
- 指定更新仅应用于行中由句点子句指定的句点部分的行值。 BUSINESS_TIME 时间段必须存在于表中 (SQLSTATE 4274M)。
- 从 value1 到 value2
- 指定更新应用于从 value1 到 value2指定的时间段内的行。 如果 value1 大于或等于 value2,或者 value1 或 value2 是空值,那么不会更新任何行 (SQLSTATE 02000)。对于使用 FROM value1 TO value2指定的时间段,更新目标中的行中的 BUSINESS_TIME 时间段为 处于以下任何状态:
- 指定句点的 与开头重叠 (如果开始列的值小于 value1 且结束列的值大于 value1)。
- 指定句点的 与结束重叠 (如果结束列的值大于或等于 value2 且开始列的值小于 value2)。
- 如果 BUSINESS_TIME 的开始列的值大于或等于 value1 ,并且相应的结束列的值小于或等于 value2,那么 完全包含 在指定的时间段内。
- 部分包含 在指定时间段内 (如果行与指定时间段的开始或指定时间段的结束重叠) ,但不能同时包含这两者。
- 如果行中的句点与指定句点的开始和结束重叠,那么 完全重叠 指定句点。
- 如果 BUSINESS_TIME 的两列都小于或等于 value1 或大于或等于 value2,那么是句点中的 未包含 。
如果行中的 BUSINESS_TIME 时间段未包含在指定的时间段内,那么不会更新该行。 否则,将根据 BUSINESS_TIME 时间段的列中的值如何与指定时间段重叠来应用更新,如下所示:- 如果行中的 BUSINESS_TIME 时间段完全包含在指定的时间段内,那么将更新该行,并且 BUSINESS_TIME 的开始列和结束列的值保持不变。
- 如果行中的 BUSINESS_TIME 时间段部分包含在指定时间段内,并且与指定时间段的开始重叠:
- 行已更新。 在更新的行中,开始列的值设置为 value1 ,结束列的值是结束列的原始值。
- 使用行中的原始值插入行,但结束列设置为 value1。
- 如果行中的 BUSINESS_TIME 时间段部分包含在指定时间段内,并且与指定时间段的结束重叠:
- 行已更新。 在更新的行中,开始列的值是开始列的原始值,结束列设置为 value2。
- 使用行中的原始值插入行,但开始列设置为 value2。
- 如果行中的 BUSINESS_TIME 时间段与指定的时间段完全重叠:
- 行已更新。 在更新的行中,开始列的值设置为 value1 ,结束列的值设置为 value2。
- 使用行中的原始值插入行,但结束列设置为 value1。
- 使用行中的原始值插入另一行,但开始列设置为 value2。
- value1 和 value2
- 对于日期或时间戳记的字符串表示,每个表达式都必须返回具有日期数据类型,时间戳记数据类型或有效数据类型的值 (SQLSTATE 428HY)。 每个表达式的结果必须与指定句点的列的数据类型相当 (SQLSTATE 42884)。 请参阅
分配和比较
中描述的比较规则。每个表达式都可以包含下列任何受支持的操作数 (SQLSTATE 428HY):- 常量
- 专用寄存器
- 变量。 有关详细信息,请参阅 对变量的引用。
- 自变量为受支持操作数的标量函数 (尽管不能使用用户定义的函数和非确定性函数)
- CAST 规范,其中,强制类型转换操作数是受支持的操作数
- 使用算术运算符和操作数的表达式
- correlation-clause
- 可以在 search-condition 或 assignment-clause 中使用,以指定表,视图,昵称或全查询。 有关 correlation-clause 的描述,请参阅
subselect
描述中的table-reference
。 包含列 - 指定当 UPDATE 语句的中间结果表嵌套在全查询的 FROM 子句中时包含的一组列以及 table-name 或 view-name的列。 包含列 将追加到为 表名 或 视图名称指定的列的列表末尾。
- INCLUDE
- 指定要包含在 UPDATE 语句的中间结果表中的列的列表。 列名称
- 指定 UPDATE 语句的中间结果表的列。 该名称不能与另一个包含列的名称相同,也不能与 table-name 或 view-name 中的列的名称相同 (SQLSTATE 42711)。 data-type
- 指定包含列的数据类型。 数据类型必须是 CREATE TABLE 语句支持的数据类型。
- SET
- 引入对列名的赋值。 assignment-clause
- 列名称
- 标识要更新的列。 如果未启用扩展指示符变量,那么 column-name 必须标识指定表,视图或昵称的可更新列,或者标识 INCLUDE 列。 类型表的对象标识列不可更新 (SQLSTATE 428DZ)。 除非列后跟 .. attribute-name (SQLSTATE 42701) ,否则不能多次指定该列。
如果它指定 INCLUDE 列,那么无法限定列名。
对于定位 UPDATE:- 如果在光标的 选择语句 中指定了 update-子句 ,那么 赋值-子句 中的每个列名也必须显示在 update-子句中。
- 如果未在游标的 select-statement 中指定 update-clause ,并且在预编译应用程序时指定了 LANGLEVEL MIA 或 SQL92E ,那么任何可更新的名称 可指定列。
- 如果未在游标的 select-statement 中指定 update-clause ,并且在预编译应用程序时显式或缺省情况下指定了 LANGLEVEL SAA1 ,那么不 列可能已更新。
.. attribute-name - 指定所设置的结构化类型的属性 (称为 属性分配)。 必须使用用户定义的结构化类型来定义指定的 column-name (SQLSTATE 428DP)。 attribute-name 必须是结构化类型 column-name 的属性 (SQLSTATE 42703)。 不涉及 .. attribute-name 子句的赋值称为 常规赋值。 expression
- 指示列的新值。 表达式是
表达式
中描述的任何类型的表达式。 表达式不能包含聚集函数,除非它出现在标量全查询中 (SQLSTATE 42903)。表达式 可能包含对 UPDATE 语句的目标表的列的引用。 对于所更新的每一行,表达式中此类列的值是更新行之前该行中的列值。
表达式不能包含对 INCLUDE 列的引用。 如果 expression 是单个主变量,那么主变量可以包含为扩展指示符变量启用的指示符变量。 如果启用了扩展指示变量,则在以下任一语句为真的情况下,不得使用默认 ((-5)或未指定(-7)的扩展指示变量值 (SQLSTATE 22539):
- 此表达式比具有显式强制转型的单个主变量更复杂
- 目标列的数据类型为结构化类型
- NULL
- 指定空值,并且只能对可空列指定 (SQLSTATE 23502)。 NULL 不能是属性赋值 (SQLSTATE 429B9) 中的值,除非它专门强制转换为属性的数据类型。
- 缺省值
- 指定应根据在表中定义相应列的方式使用缺省值。 插入的值取决于列的定义方式。
- 如果根据表达式将列定义为生成的列,那么系统将根据该表达式生成列值。
- 如果列是使用 IDENTITY 子句定义的,那么值由数据库管理器生成。
- 如果使用 WITH DEFAULT 子句定义了该列,那么该值将设置为为该列定义的缺省值 (请参阅
ALTER TABLE
中的 default-clause )。 - 如果使用 NOT NULL 子句定义了列,并且未使用 GENERATED 子句,或者未使用 WITH DEFAULT 子句,或者使用了 DEFAULT NULL ,那么不能对该列指定 DEFAULT 关键字 (SQLSTATE 23502)。
- 如果列是使用 ROW CHANGE TIMESTAMP 子句定义的,那么该值由数据库管理器生成。
可以将使用 GENERATED ALWAYS 子句定义的生成列的唯一值设置为 DEFAULT (SQLSTATE 428C9)。
DEFAULT 关键字不能用作属性分配中的值 (SQLSTATE 429B9)。
对于数据源不支持 DEFAULT 语法的昵称, DEFAULT 关键字不能用作赋值以进行更新。
row-fullselect - 指定返回单行的全查询。 结果列值将分配给每个相应的 column-name。 如果全查询未返回任何行,那么会将空值分配给每个列;如果要更新的任何列都不可空,那么将发生错误。 如果结果中存在多个行,那么也会发生错误。
row-fullselect 可能包含对 UPDATE 语句的目标表的列的引用。 对于所更新的每一行,表达式中此类列的值是更新行之前该行中的列值。 如果结果中有多个行,那么返回错误 (SQLSTATE 21000)。
- 标识要更新的列。 如果未启用扩展指示符变量,那么 column-name 必须标识指定表,视图或昵称的可更新列,或者标识 INCLUDE 列。 类型表的对象标识列不可更新 (SQLSTATE 428DZ)。 除非列后跟 .. attribute-name (SQLSTATE 42701) ,否则不能多次指定该列。
- FROM
指定为目标表列的分配提供值的源表的列表。 源表通过指定连接条件的 WHERE 子句与目标表隐式内部连接。 目标表中满足 WHERE 条件的行将使用源表行中的值进行更新。
当 UPDATE 语句指定 FROM 子句时:- 更新操作的目标不能是昵称。
- 更新操作的源不能是 analyze_table-expression (即,数据挖掘模型的结果) 或 data-change-table-reference (即,嵌套 UPDATE , DELETE 或 INSERT 语句的结果)。
有关 table-reference的描述,请参阅 table-reference。
- WHERE
- 引入用于指示要更新的行的条件。 您可以省略该子句,提供搜索条件或命名游标。 如果省略该子句,那么将更新表,视图或昵称的所有行。
- search-condition
- 除子查询外,搜索条件中的每个 column-name 都必须命名表,视图或昵称的列。 当搜索条件包含同一表同时是 UPDATE 和子查询的基本对象的子查询时,将在更新任何行之前对该子查询进行完全求值。
搜索条件将应用于表,视图或昵称的每行,而更新的行是搜索条件结果为 true 的行。
如果搜索条件包含子查询,那么可以将该子查询视为每次将搜索条件应用于行时执行的子查询,以及应用搜索条件时使用的结果。 实际上,没有相关引用的子查询仅执行一次,而具有相关引用的子查询可能必须针对每一行执行一次。
- CURRENT OF 游标名称
- 标识要在更新操作中使用的游标。 cursor-name 必须标识已声明的游标,如
DECLARE CURSOR
中所述。 DECLARE CURSOR 语句必须在程序中的 UPDATE 语句之前。还必须在游标的 SELECT 语句的 FROM 子句中指定指定的表,视图或昵称,并且游标的结果表不得为只读。 (有关只读结果表的说明,请参阅
DECLARE CURSOR
。)执行 UPDATE 语句时,光标必须位于一行上; 该行已更新。
如果游标引用了以下内容,那么不能使用此格式的 UPDATE (SQLSTATE 42828):- 定义了 INSTEAD OF UPDATE 触发器的视图
- 在定义视图的全查询的选择列表中包含 OLAP 函数的视图
- 使用 WITH ROW MOVEMENT 子句直接或间接定义的视图
排序子句 - 除子查询外,搜索条件中的每个 column-name 都必须命名表,视图或昵称的列。 当搜索条件包含同一表同时是 UPDATE 和子查询的基本对象的子查询时,将在更新任何行之前对该子查询进行完全求值。
- 指定用于应用 offset-clause 和 fetch-clause的行的顺序。 指定 order-by-子句 以确保根据 offset-子句 和 fetch-子句确定要更新的行集的可预测顺序。 有关 order-by-clause的详细信息,请参阅 order-by-clause。 offset-子句
- 通过跳过部分符合条件的行来限制更新的效果。 有关 offset-clause的详细信息,请参阅 offset-clause。 fetch-子句
- 将更新的效果限制为限定行的子集。 有关 fetch-clause的详细信息,请参阅 fetch-clause。
- WITH
- 指定执行 UPDATE 语句的隔离级别。
- RR
- 可重复读取
- RS
- 读稳定性
- CS
- 游标稳定性
- UR
- 未落实的读
- 跳过已锁定的数据
- SKIP LOCKED DATA 子句指定当其他事务在某些行上持有会阻止语句执行的不兼容锁定时会跳过这些行。 这些行可以属于语句中寻址的任何被访问表(包括子查询中访问的表)。 当隔离级别为 CS 或 RS 时,此子句才适用;当 UR 或 RR 隔离级别生效时,将忽略此子句。 它适用于行和块级别锁定。
调用
如果是在 WITH RR 或 WITH UR 中指定,那么将忽略 SKIP LOCKED DATA。 该语句的缺省隔离级别取决于该语句所绑定的包或计划的隔离程度以及结果表是否为只读。 如果该语句的缺省隔离级别是可重复的读取或未落实的读取,那么将忽略 SKIP LOCKED DATA。
- NOWAIT / WAIT <时间 秒>
- 注意: Db2 11.5.6 及更高版本中提供了以下功能。
NOWAIT 和 WAIT 子句指定在返回一个指示无法获得锁定的错误之前等待锁定的秒数。
使用 WAIT 子句时,"<time sec>是介于-1和 32767 之间的整数。注: 对于如果指定了 WAIT 值NOWAIT和WAIT 0,不会等待锁定。 如果在请求时无可用的锁定,那么将返回 -911 错误。-1,那么将关闭锁定超时检测。 在这种情况下,将等待一个锁定(如果在请求时无可用的锁定),直到发生以下任一事件:- 将授予锁定。
- 发生死锁。
虽然 NOWAIT 和 WAIT 子句不允许用于定位更新和删除,但您可以在游标的声明中使用它们。 在游标声明中使用时,使用此游标的语句将继承指定的等待时间值。
规则
- 触发器: UPDATE 语句可能导致执行触发器。 触发器可能导致执行其他语句,或者可能根据更新值产生错误条件。 如果视图上的更新操作导致 INSTEAD OF 触发器触发,那么将根据触发器中执行的更新而不是导致触发器触发的视图或其底层表来检查有效性,引用完整性和约束。
- 分配: 根据特定分配规则将更新值分配给列。
- 有效性: 更新后的行必须符合更新后的列上的任何唯一索引对表 (或视图的基本表) 施加的任何约束。
如果使用未使用 WITH CHECK OPTION 定义的视图,那么可以更改行以使它们不再符合视图的定义。 此类行将在视图的基本表中进行更新,并且不再显示在视图中。
如果使用了使用 WITH CHECK OPTION 定义的视图,那么更新后的行必须符合该视图的定义。 有关管理此情境的规则的说明,请参阅
CREATE VIEW
。 - 检查约束: 更新值必须满足对表定义的检查约束的检查条件。
对定义了检查约束的表的 UPDATE 具有针对更新后的每行更新一次的每列的约束条件。 处理 UPDATE 语句时,仅检查引用已更新的列的检查约束。
- 引用完整性: 如果更新规则为 RESTRICT 并且存在一个或多个从属行,那么无法更改父唯一键的值。 但是,如果更新规则为 NO ACTION,并且更新语句完成时每个子代都有父键,那么父代唯一键可以更新。 外键的非空更新值必须等于关系的父表的主键值。
- XML 值: 更新 XML 列值时,新值必须是格式正确的 XML 文档 (SQLSTATE 2200M)。
- 安全策略: 如果标识的表或标识的视图的基本表受安全策略保护,那么会话授权标识必须具有基于标签的访问控制 (LBAC) 凭证,这些凭证允许:
- 对正在更新的所有受保护列的写访问权 (SQLSTATE 42512)
- 对带 RESTRICT NOT AUTHORIZED WRITE SECURITY LABEL 选项创建的安全策略的 DB2SECURITYLABEL 列提供的任何显式值的写访问权 (SQLSTATE 23523)
- 对正在更新的所有行的读写访问权 (SQLSTATE 42519)
如果对 DB2SECURITYLABEL 列使用隐式值,则会话授权标识还必须被授予安全标签以获取安全策略的写访问权,(SQLSTATE 23523),这可能在以下情况下发生:
- DB2SECURITYLABEL 列未包含在要更新的列列表中(因此它针对安全标签隐式更新以使会话授权标识获取写访问权)
- 已明确提供 DB2SECURITYLABEL 列的值,但会话授权标识没有对该值的写访问权,并且安全策略是带 OVERRIDE NOT AUTHORIZED WRITE SECURITY LABEL 选项创建的
- 扩展指标变量使用:如果启用,则不得输入 0(零)到-7以外的指示变量值(SQLSTATE 22010)。 此外,如果已启用,那么扩展指示符变量值 default 和 unassigned 不能出现在不受支持的上下文中 (SQLSTATE 22539)。
- 扩展指示符变量: 在 UPDATE 语句的 赋值子句 中,这是一个 表达式 ,它是对单个主变量的引用,或者是作为主变量的主变量 显式强制类型转换可能导致分配扩展指示符变量值。 将基于变量的扩展指示符值指定为 unassigned 具有将目标列设置为其当前值的效果,就像未在语句中指定一样。 分配基于扩展指示符变量的缺省值将分配列的缺省值。 有关数据类型的缺省值的信息,请参阅 DEFAULT 子句 在 "CREATE TABLE" 语句中的描述。
如果目标列不可更新(例如,定义为表达式的视图中的列),则它必须被分配扩展指示符变量值 unassigned (SQLSTATE 42808)。
如果目标列是定义为 GENERATED ALWAYS 的列,则它必须被分配 DEFAULT 关键字,或基于扩展指示符变量的值 default 或 unassigned (SQLSTATE 428C9)。
UPDATE 语句不得将所有目标列分配给基于扩展指示符变量的值 unassigned (SQLSTATE 22540)。
注意
- 如果更新值违反任何约束,或者在执行 UPDATE 语句期间发生任何其他错误,那么不会更新任何行。 未定义多行的更新顺序。
- 对使用 WITH ROW MOVEMENT 子句定义的视图的更新可能会导致对视图的底层表执行删除操作和插入操作。 有关详细信息,请参阅 CREATE VIEW 语句的描述。
- 当 UPDATE 语句完成执行时, SQLCA 中 SQLERRD (3) 的值是符合更新操作条件的行数。 在 SQL 过程语句的上下文中,可以使用 GET DIAGNOSTICS 语句的 ROW_COUNT 变量来检索该值。 SQLERRD (5) 字段包含所有已激活触发器插入,删除或更新的行数。
- 除非已存在适当的锁定,否则执行成功的 UPDATE 语句将获取一个或多个互斥锁定。 在释放锁定之前,执行更新的应用程序进程只能访问更新后的行 (使用未落实的读隔离级别的应用程序除外)。 有关锁定的更多信息,请参阅 COMMIT , ROLLBACK 和 LOCK TABLE 语句的描述。
- 更新类型表的列分布统计信息时,必须指定首次引入该列的子表。
- 同一结构化类型列上的多个属性分配按 SET 子句中指定的顺序进行,并且在括号内的 set 子句中按从左到右的顺序进行。
- 属性赋值调用用户定义的结构化类型的属性的 mutator 方法。 例如,赋值
st..a1=x与在赋值st = st..a1(x)中使用 mutator 方法具有相同的效果。 - 虽然给定列只能是一个常规赋值中的目标列,但一个列可以是多个属性赋值中的目标列 (但前提是它不是常规赋值中的目标列)。
- 当定义为单值类型的标识列更新时,将在源类型中完成整个计算,并在实际将值分配给列之前将结果强制转换为单值类型。 (在计算之前,不会将先前值强制转换为源类型。)
- 要在标识列的 SET 语句上生成值,请使用 DEFAULT 关键字:
在此示例中, NEW.EMPNO 定义为标识列,并生成用于更新此列的值。SET NEW.EMPNO = DEFAULT - 有关使用标识列的已生成序列的值或有关超过标识列的最大值的更多信息,请参阅
INSERT
。 - 对于分区表, UPDATE WHERE CURRENT OF cursor-name 操作可以将行从一个数据分区移至另一个数据分区。 发生此情况后,光标不再位于该行上,并且无法对该行进行进一步的 UPDATE WHERE CURRENT OF cursor-name 修改。 但是,可以访存游标中的下一行。
- 对于使用 ROW CHANGE TIMESTAMP 子句定义的列,在更新行时始终会更改该值。 如果未在 SET 列表中显式指定该列,那么数据库管理器仍会为该行生成值。 该值对于数据库分区中的每个表分区都是唯一的,并且设置为对应于行更新的近似时间戳记。
- 扩展指示符变量和更新触发器:如果目标列已被分配基于扩展指示符变量的值 unassigned,那么不会将该列视为已更新。 该列被视为未在目标表上定义的任何更新触发器的 OF column-name 列表中指定。
- 扩展指示符变量和延迟错误检查: 当启用扩展指示符变量时,除了静态 UPDATE 语句的列级别更新特权检查之外,将延迟到语句执行时进行验证,否则将在语句准备中执行验证以识别不可更新的列的更新。 是否应该报告错误只能在执行期间根据指示符值来确定。 在绑定处理期间继续执行对静态 UPDATE 语句的列级别更新特权的检查,即使启用了扩展指示符变量也是如此。
- 系统周期时态表的注意事项: 如果视图是使用 WITH CHECK OPTION 定义的,并且视图定义包含包含下列其中一个语法元素的 WHERE 子句,那么 UPDATE 语句的目标不得是引用 FROM 子句中后跟 SYSTEM_TIME 的句点规范的视图的全查询 (SQLSTATE 51046):
- 一个直接或间接地引用了系统时间段时间表的子查询
- 对具有相关联程序包的 SQL 例程进行的调用
- 使用非 NO SQL 的数据访问指示调用外部例程
如果 CURRENT TEMPORAL SYSTEM_TIME 专用寄存器设置为非空值,那么 UPDATE 语句的底层目标不得是系统时间段时态表 (SQLSTATE 51046) ,并且如果视图定义包含包含下列其中一个语法元素的 WHERE 子句,那么 UPDATE 语句的目标不得是使用 WITH CHECK OPTION 定义的视图 (SQLSTATE 51046):- 一个直接或间接地引用了系统时间段时间表的子查询
- 对具有相关联程序包的 SQL 例程进行的调用
- 使用非 NO SQL 的数据访问指示调用外部例程
更新系统时间段时态表的行时,数据库管理器会更新 row-begin 和 transaction-start-ID 列的值,如下所示:- 将为行开始列分配一个值,该值是在执行事务中的第一个数据更改语句期间使用时间时钟读数生成的,该值要求将值分配给表中的行开始列或事务开始标识列,或者删除系统时间段时态表中的行。 数据库管理器确保跨事务的行开始列的生成值的唯一性。 可以调整时间戳记值,以确保插入到关联历史记录表中的行的结束时间戳记值大于当冲突事务更新系统时间段时态表中的同一行时可能发生的开始时间戳记值。 必须将数据库配置参数 systime_period_adj 设置为 "是" ,才能在时间戳记值中进行此调整。 如果在单个 SQL 事务中更新了多行,并且不需要进行调整,那么行开始列的值对于所有行都是相同的,并且与为另一个事务的列生成的值是唯一的。
- 为事务开始标识列分配了每个事务的唯一时间戳记值或空值。如果该列可空并且表中有行开始列,那么会将空值分配给事务开始标识列,而无需调整该值。 否则,将在执行事务中的第一个数据更改语句期间使用时间时钟的读数来生成该值,该语句要求将值分配给表中的行开始或事务开始标识列,或者删除系统周期时态表中的行。 如果在单个 SQL 事务中更新了多行,那么事务开始标识列的值对于所有行都是相同的,并且与针对另一个事务的列生成的值是唯一的。
如果 UPDATE 语句具有包含相关子查询的搜索条件,该子查询引用历史记录行 (显式引用历史记录表名的名称或通过在 FROM 子句中使用句点规范来隐式引用) ,那么作为历史记录行 (如果有) 插入到历史记录表中的已更新行的旧版本可能会显示为更新随后为该语句处理的行的操作。
如果满足以下两个条件,那么 UPDATE 语句的目标不能是引用 FROM 子句中后跟 SYSTEM_TIME 的句点规范的视图的全查询 (SQLSTATE 51046):- 该视图是使用 WITH CHECK OPTION 定义的。
- 视图定义包含包含下列其中一个语法元素的 WHERE 子句:
- 引用系统周期时态表 (直接或间接) 的子查询。
- 对具有关联包的 SQL 例程的调用。
- 使用非 NO SQL 的数据访问指示调用外部例程。
如果 CURRENT TEMPORAL SYSTEM_TIME 专用寄存器设置为非空值,那么 UPDATE 语句的底层目标 (直接或间接) 不能是系统时间段时态表 (SQLSTATE 51046)。
如果 CURRENT TEMPORAL SYSTEM_TIME 专用寄存器设置为非空值,那么如果视图定义包含包含下列其中一个语法元素的 WHERE 子句,那么 UPDATE 语句的目标不能是使用 WITH CHECK OPTION 定义的视图 (SQLSTATE 51046):- 引用系统周期时态表 (直接或间接) 的子查询。
- 对具有关联包的 SQL 例程的调用。
- 使用非 NO SQL 的数据访问指示调用外部例程。
- 历史记录表的注意事项: 更新系统时间段时态表的行时,会将该行的历史记录副本插入到相应的历史记录表中,并以与数据更改操作时间对应的系统确定的值的形式捕获历史记录行的结束时间戳记。 数据库管理器指定在事务中执行第一个数据更改语句期间使用时间时钟读数生成的值,该值要求将值分配给表中的行 begin 或 transaction start-ID 列,或者删除系统时间段时态表中的行。 数据库管理器确保为历史记录表中的结束列生成的值在事务中的唯一性。 可以调整时间戳记值,以确保插入到历史记录表中的行的结束时间戳记值大于当有冲突的事务更新系统时间段时态表中的同一行时可能发生的开始时间戳记值 (SQLSTATE 01695)。 必须将数据库配置参数 systime_period_adj 设置为 "是" ,才能在时间戳记值中进行此调整。
对于更新操作,调整仅影响与系统时间段时态表关联的历史记录表中的行结束列对应的结束列的值。 在对表的后续引用中考虑这些调整,是否在与关联系统时间段时态表中的时间段的行开始列和行结束列对应的列的值中搜索事务开始时间。
- 应用程序时间段时态表的注意事项: 如果视图是使用 WITH CHECK OPTION 定义的,并且视图定义包含包含下列其中一个语法元素的 WHERE 子句,那么 UPDATE 语句的目标不得是引用 FROM 子句中后跟 BUSINESS_TIME 的时间段规范的视图的全查询 (SQLSTATE 51046):
- 一个直接或间接地引用了应用程序时间段时间表的子查询
- 对具有相关联程序包的 SQL 例程进行的调用
- 使用非 NO SQL 的数据访问指示调用外部例程
如果 CURRENT TEMPORAL BUSINESS_TIME 专用寄存器设置为非空值,那么如果视图定义包含包含下列其中一个语法元素的 WHERE 子句,那么 UPDATE 语句的目标不得是使用 WITH CHECK 选项定义的视图 (SQLSTATE 51046):- 一个直接或间接地引用了应用程序时间段时间表的子查询
- 对具有相关联程序包的 SQL 例程进行的调用
- 使用非 NO SQL 的数据访问指示调用外部例程
包含 FOR 部分 BUSINESS_TIME 子句的应用程序时间段时态表的 UPDATE 语句指示指定的更新在哪个两个时间点之间生效。 如果指定了 FOR 部分 BUSINESS_TIME ,并且行的句点值 (由行开始列和行结束列的值指定) 仅部分包含在从 value1 到 value2指定的句点中,那么将更新该行,并且将自动插入一行或两行以表示未更改的行部分。 对于由于对表执行更新操作而自动插入的每行,将为应用程序时间段时态表中的每个生成列生成新值。 如果生成的列被定义为唯一键或主键、引用约束中的父键或唯一索引的一部分,则自动插入可能会违反约束或索引,在这种情况下会返回错误。
如果将行插入到具有主键或唯一约束 (定义了 BUSINESS_TIME 无重叠子句) 或唯一索引 (定义了 BUSINESS_TIME 无重叠子句) 的应用程序时间段时态表中,如果 BUSINESS_TIME 时间段的开始列和结束列定义的时间段与表中具有相同唯一约束或唯一索引的另一行的 BUSINESS_TIME 时间段的开始列和结束列定义的时间段重叠,那么将返回错误。
如果满足以下两个条件,那么 UPDATE 语句的目标不能是引用 FROM 子句中的视图并后跟 BUSINESS_TIME 的句点规范的全查询 (SQLSTATE 51046):- 该视图是使用 WITH CHECK OPTION 定义的。
- 视图定义包含包含下列其中一个语法元素的 WHERE 子句:
- 引用应用程序周期时态表 (直接或间接) 的子查询。
- 对具有关联包的 SQL 例程的调用。
- 使用非 NO SQL 的数据访问指示调用外部例程。
如果 CURRENT TEMPORAL BUSINESS_TIME 专用寄存器设置为非空值,那么如果视图定义包含包含下列其中一个语法元素的 WHERE 子句,那么 UPDATE 语句的目标不能是使用 WITH CHECK OPTION 定义的视图 (SQLSTATE 51046):- 引用应用程序周期时态表 (直接或间接) 的子查询。
- 对具有关联包的 SQL 例程的调用。
- 使用非 NO SQL 的数据访问指示调用外部例程。
当应用程序周期时态表是 UPDATE 语句的目标时, CURRENT TEMPORAL BUSINESS_TIME 专用寄存器的生效值不是空值,并且 BUSTIMESENSITIVE 绑定选项设置为 YES 时,将隐式使用以下附加谓词:
其中bt_begin <= CURRENT TEMPORAL BUSINESS_TIME AND bt_end > CURRENT TEMPORAL BUSINESS_TIMEbt_begin和bt_end是 UPDATE 语句目标表的 BUSINESS_TIME 周期的开始列和结束列。 - 应用程序周期时态表和触发器的注意事项: 当更新行并指定 FOR 部分 BUSINESS_TIME 子句时,可以隐式插入其他行以反映未更新的行的任何部分。 已对更新的行激活所有现有更新触发器,并且已对隐式插入的行激活所有现有插入触发器。
示例
- 示例 1: 将 EMPLOYEE 表中职员编号 (EMPNO) "000290" 的作业 (JOB) 更改为 "LABER"。
UPDATE EMPLOYEE SET JOB = 'LABORER' WHERE EMPNO = '000290' - 示例 2: 对于部门 (DEPTNO) "D21" 在 PROJECT 表中负责的所有项目,将项目人员配置 (PRSTAFF) 增加 1.5 。
UPDATE PROJECT SET PRSTAFF = PRSTAFF + 1.5 WHERE DEPTNO = 'D21' - 示例 3: 已临时重新分配除部门经理 (WORKDEPT) "E21" 以外的所有员工。 通过将其作业 (JOB) 更改为空值并在 EMPLOYEE 表中将其薪资 (SALARY , PAY , COMM) 值更改为零来指示这一点。
UPDATE EMPLOYEE SET JOB=NULL, SALARY=0, BONUS=0, COMM=0 WHERE WORKDEPT = 'E21' AND JOB <> 'MANAGER'此语句也可写如下。UPDATE EMPLOYEE SET (JOB, SALARY, BONUS, COMM) = (NULL, 0, 0, 0) WHERE WORKDEPT = 'E21' AND JOB <> 'MANAGER' - 示例 4: 将员工编号为 000120 的员工的工资和佣金列分别更新为已更新行的部门的员工的工资和佣金的平均值。
上一个语句在语义上等同于以下语句,但只需要对 EMPLOYEE 表进行一次访问,而以下语句指定了 EMPLOYEE 表两次。UPDATE (SELECT EMPNO, SALARY, COMM, AVG(SALARY) OVER (PARTITION BY WORKDEPT), AVG(COMM) OVER (PARTITION BY WORKDEPT) FROM EMPLOYEE E) AS E(EMPNO, SALARY, COMM, AVGSAL, AVGCOMM) SET (SALARY, COMM) = (AVGSAL, AVGCOMM) WHERE EMPNO = '000120'UPDATE EMPLOYEE EU SET (EU.SALARY, EU.COMM) = (SELECT AVG(ES.SALARY), AVG(ES.COMM) FROM EMPLOYEE ES WHERE ES.WORKDEPT = EU.WORKDEPT) WHERE EU.EMPNO = '000120' - 示例 5: 在 C 程序中,显示 EMPLOYEE 表中的行,然后根据请求将某些员工的作业 (JOB) 更改为键入的新作业。
EXEC SQL DECLARE C1 CURSOR FOR SELECT * FROM EMPLOYEE FOR UPDATE OF JOB; EXEC SQL OPEN C1; EXEC SQL FETCH C1 INTO ... ; if ( strcmp (change, "YES") == 0 ) EXEC SQL UPDATE EMPLOYEE SET JOB = :newjob WHERE CURRENT OF C1; EXEC SQL CLOSE C1; - 示例 6: 这些示例更改列对象的属性。假定存在以下类型和表:
CREATE TYPE POINT AS (X INTEGER, Y INTEGER) NOT FINAL WITHOUT COMPARISONS MODE DB2SQLCREATE TYPE CIRCLE AS (RADIUS INTEGER, CENTER POINT) NOT FINAL WITHOUT COMPARISONS MODE DB2SQLCREATE TABLE CIRCLES (ID INTEGER, OWNER VARCHAR(50), C CIRCLE以下示例通过更改 OWNER 列以及标识为 999 的 CIRCLE 列的 RADIUS 属性来更新 CIRCLE 表:UPDATE CIRCLES SET OWNER = 'Bruce' C..RADIUS = 5 WHERE ID = 999以下示例转置由 999 标识的圆心的 X 和 Y 坐标:UPDATE CIRCLES SET C..CENTER..X = C..CENTER..Y, C..CENTER..Y = C..CENTER..X WHERE ID = 999以下示例是另一种写上述两种语句的方法。 此示例组合了上述两个示例的效果:UPDATE CIRCLES SET (OWNER,C..RADIUS,C..CENTER..X,C..CENTER..Y) = ('Bruce',5,C..CENTER..Y,C..CENTER..X) WHERE ID = 999 - 示例 7: 将 DOCID 为 "001" 的 DOCUMENTS 表的 XMLDOC 列更新为从 XMLTEXT 表中选择并解析的字符串。
UPDATE DOCUMENTS SET XMLDOC = (SELECT XMLPARSE(DOCUMENT C1 STRIP WHITESPACE) FROM XMLTEXT WHERE TEXTID = '001') WHERE DOCID = '001' - 示例 8: 已向项目表添加新的位置列。 使用处理项目的部门的位置更新项目位置。
UPDATE PROJECT P SET P.LOCATION = D.LOCATION FROM DEPARTMENT D WHERE P.DEPTNO = D.DEPTNO; - 示例 9: 将估算的项目人员配置更新为项目中所有活动所需的最大人员配置。
UPDATE PROJECT P SET P.PRSTAFF = S.ACSTAFF FROM (SELECT PROJNO, MAX(ACSTAFF) ACSTAFF FROM PROJACT GROUP BY PROJNO) S WHERE P.PROJNO = S.PROJNO AND P.PROJNAME = 'PAYROLL PROGRAMMING'; - 示例 10: 将员工的工作部门更新为分配给他的项目部门。
UPDATE EMPLOYEE E SET E.WORKDEPT = P.DEPTNO FROM PROJECT P JOIN EMPPROJACT EP ON P.PROJNO = EP.PROJNO WHERE E.EMPNO = EP.EMPNO AND E.FIRSTNME = 'PHILIP' AND E.LASTNAME = 'SMITH';
