MERGE 语句

FL 500 MERGE 语句使用源数据(表引用或指定输入数据的结果)更新目标(表或视图)。 目标中与输入数据匹配的行可以按指定方式删除或更新,目标中不存在的行可以插入。 如果视图上没有定义“代替”触发器,则更新、删除或插入视图中的行,也会更新、删除或插入视图所基于的表中的行。

调用 MERGE

此语句可嵌入应用程序中或者以交互方式发出。 它是可动态准备的可执行语句。

授权 MERGE

以下定义的特权集所包含的特权必须至少包括以下特权之一:

  • SYSADM 权限
  • 对表的所有权
  • DATAACCESS 权限
  • 如果搜索条件包含对表或视图某一列的引用,则引用表或视图的 SELECT 权限
  • 如果指定了删除操作,则表或视图的删除权限
  • 如果指定了插入操作,则表或视图的插入权限
  • 如果指定了更新操作,则至少需要以下权限之一:
    • 表或视图的更新权限
    • 每列的更新权限
    • 如果分配条款的右侧包含对表格或视图某一列的引用,则引用表格或视图的 SELECT 权限

如果数据库是隐式创建的,则数据库权限必须位于隐式数据库或 DSNDB04 上。

如果插入操作或赋值子句包含子查询,则权限集所拥有的权限必须至少包括以下权限之一:

  • SYSADM 权限
  • 子查询中确定的每个表或视图的 SELECT 权限
  • 子查询中确定的表或视图的所有权
  • DATAACCESS 权限

权限设置:

如果语句嵌入到应用程序中,权限集就是计划或软件包所有者所拥有的权限。 如果语句是动态编写的,则权限集由生效的 DYNAMICRULES 行为(运行、绑定、定义或调用)决定, 如表 1 所示。 (有关这些行为的更多信息,包括决定这些行为的 DYNAMICRULES 绑定选项值列表,请参阅授权 ID 和动态 SQL

MERGE的语法

阅读语法图跳过可视化语法图 MERGE INTO table-name视图名称 correlation-clause1包括列 USING 表引用1源值 ON 搜索条件 WHENmatching-conditionTHENmodification-operation信号语句1 ELSE IGNORE1 NOT ATOMIC CONTINUE ON SQLEXCEPTION QUERYNO整数
注意:
  • 1 指定此条款的规则受NOT ATOMIC条款或USING条款中源值的影响。 更多信息,请参阅 MERGE语句规则

相关条款:

阅读语法图跳过可视化语法图AS相关名称(,列名)

包括列:

阅读语法图跳过可视化语法图 INCLUDE ( ,列名数据类型 )

数据类型:

阅读语法图跳过可视化语法图built-in-type独特类型

内置类型:

阅读语法图跳过可视化语法图SMALLINTINTEGERINTBIGINTDECIMALDECNUMERIC(5,0)( 整数,0, 整数)FLOAT(53)( 整数)REALDOUBLEPRECISIONDECFLOAT(34)(16)CHARACTERCHAR(1)( 整数)CHARACTERCHARVARYINGVARCHAR( 整数)FOR BIT DATAGRAPHIC(1)( 整数)VARGRAPHIC( 整数)BINARY(1)( 整数)BINARY VARYINGVARBINARY( 整数)DATETIMETIMESTAMP(6)(整数)WITHOUT TIME ZONEWITH TIME ZONE

源值:

阅读语法图跳过可视化语法图(价值观单排价值观多行值) AS 相关名称 (,列名)
注意:

值-单行:

阅读语法图跳过可视化语法图 表达式NULL(,表达式NULL)

多行值:

阅读语法图跳过可视化语法图 表达式主机变量数组NULL(,表达式主机变量数组NULL) FOR 宿主变量常数 ROWS1
注意:
  • 1 对于静态MERGE语句,如果未指定FOR n ROWS,则 values-multiple-row 被视为 values-single-row。 对于动态MERGE语句,不需要在MERGE语句中指定FOR n ROWS。 它可以在EXECUTE语句中指定,但不能同时在MERGE和EXECUTE语句中指定。

匹配条件:

阅读语法图跳过可视化语法图 NOT MATCHED AND搜索条件1
注意:
  • 1 指定此条款的规则受NOT ATOMIC条款或USING条款中源值的影响。 更多信息,请参阅 MERGE语句规则

修改-操作:

阅读语法图跳过可视化语法图update-operationdelete-operation1insert-operation
注意:
  • 1 指定此条款的规则受NOT ATOMIC条款或USING条款中源值的影响。 更多信息,请参阅 MERGE语句规则

assignment-clause:

阅读语法图跳过可视化语法图,列名=表达式DEFAULTNULL(,列名)=(,表达式1DEFAULTNULL行-全选23)
注意:
  • 1 表达式、DEFAULT和NULL关键字的数量必须与列名称的数量一致。
  • 2 SELECT列表中的列数必须与列名数一致。
  • 3 指定此条款的规则受非原子性条款或具有源值的 “使用”条款的影响。 欲了解更多信息,请发送电子邮件至 MERGE语句规则.

更新操作:

阅读语法图跳过可视化语法图 UPDATE SETassignment-clause

删除操作:

阅读语法图跳过可视化语法图 DELETE

插入操作:

阅读语法图跳过可视化语法图 INSERT (,列名) VALUES 表达式DEFAULTNULL1(,表达式DEFAULTNULL)2
注意:
  • 1 表达式、DEFAULT和NULL关键字的数量必须与列名称的数量一致。
  • 2 SELECT列表中的列数必须与列名数一致。

描述 MERGE

INTO 表名视图名
更改开始FL 500确定合并的更新、插入或删除操作的目标。 名称必须标识当前服务器上存在的表或视图。 名称不得识别: 更改结束
  • 目录表
  • 更改开始目录表更改结束
  • 创建的全球临时表
  • 只读视图
  • 系统维护的实体化查询表
  • 为XML列隐式创建的表
  • 只含加速器的表格

如果将视图指定为MERGE语句的目标,则该视图不得定义任何INSTEAD OF触发器。

AS 关联名称
更改开始FL 500correlation-name 提供了一个替代名称,可在引用目标表列时使用。

关联名称可以在搜索条件 、匹配条件中使用,也可以作为赋值源值的一部分,用于指定目标表或视图。 关联名称用于限定对表或视图列的引用。 有关 correlation-clause 的说明,请参见表格-参考

column-name
指定列名。 当指定关联名称时,也可以指定列名 ,为目标表名视图名的列命名。 如果指定了列列表,则表或视图中的每一列都必须有一个列列表中的名称。
更改结束
包括列
指定一组列,当MERGE语句嵌套在SELECT语句或SELECT INTO语句中使用的外部全选语句的FROM子句中时,这些列与指定表或视图的列一起包含在MERGE语句的结果表中。 包含的列附加到以表名视图名标识的列列表的末尾。 如果未为包含的列指定值,则该列返回空值。
INCLUDE
介绍MERGE语句结果表中包含的列列表。 仅当MERGE语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,包含的列才可用。 只有在MERGE语句嵌套在SELECT语句的FROM子句中时,才能指定INCLUDE。
列名
指定 MERGE 语句的结果表的列名,该列名与另一个包含的列或者在 table-nameview-name 中指定的表或视图中的列名不同。
数据类型
指定包含列的数据类型。 包含的列可以为空。
以下数据类型的列不能用作包含列:
  • 长字符串,
  • 长方图形,
  • XML
  • LOB
  • 基于所列数据类型的不同类型。
built-in-type
指定内置数据类型。 有关每种内置类型的描述,请参见 CREATE TABLE语句

INCLUDE列中不能指定CCSID 1208和CCSID 1200子句。

独特类型
指定一种不同的类型。 列的任何长度、精度或比例属性都是通过使用CREATE TYPE语句指定的不同类型的源类型的属性。
更改开始USING更改结束
更改开始FL 500指定一组行,作为要合并到目标中的结果表。
表引用
指定要作为结果表合并到目标的一组行。 如果结果表为空,则返回警告。

更改开始如果指定了 table-reference ,则不得指定 NOT ATOMIC 子句和 VALUES 值-多行有关详细信息,请参阅 MERGE 语句的规则更改结束

源值
VALUES 值-单行值-多行

将一组行的值指定为合并到目标中的结果表。 values-single-row 指定单行源数据。 values-multiple-row 指定多行源数据。 更改开始数值数量不得超过 750。更改结束

更改开始如果指定了 VALUES values-single-rowVALUESvalues-multiple-row ,则不得指定表格引用;如果指定了VALUES values-multiple-row ,则必须指定 NOT ATOMIC CONTINUE ON SQLEXCEPTION。 有关详细信息,请参阅 MERGE 语句的规则更改结束

表达式
指定表达式中描述的表达式类型。 表达式中不能包含列名。 表达式不能引用下一个值或上一个值表达式。 如果表达式是一个宿主变量,则该宿主变量可以标识一个结构体。 任何指定的宿主变量或结构都必须根据宿主结构和变量的声明规则在应用程序中进行描述。
主机变量数组
指定一个宿主变量数组。 每个宿主变量数组必须在应用程序中根据数组声明规则进行定义。 宿主变量数组包含要合并到目标列中的数据。 行数必须小于或等于每个宿主变量数组的维度。 可以为每个主机变量数组指定可选的指示器数组。 如果任何SQLVAR的SQLTYPE表明某列为空值,则应指定指示数组。 指示器阵列可用于扩展指示器变量。 指示器阵列的尺寸必须足够大,以便为每行输入数据容纳一个指示器。

主机变量数组不支持主机结构。

C/C++、 COBOL 和 PL/I 支持 host-variable-array。 更多信息,请参阅主机变量数组

NULL
指定一个空值。

在源值中与 NULL 关键字对应的列名用于确定空值的数据类型。 在源值中指定的列名必须在 MERGE 语句的其他地方引用,以便根据其使用的上下文确定其数据类型,并且所有此类引用必须解析为相同的数据类型。 日期时间数据类型和字符串类型(CHAR或VARCHAR)被视为同一类型。

对于宿主变量整数常量
指定要合并的行数。 对于动态MERGE语句,可以在EXECUTE语句中指定此子句。 host-variableinteger-constant 被赋值 k。 如果指定了宿主变量 ,则该变量必须为精确数值类型,且比例系数为零,且不得包含指示变量。 k 必须在 1–32767 范围内。k 行从指定的源数据合并到目标中。

如果在 FOR n ROWS 中指定了参数标记,则必须在关联的 EXECUTE 语句的 USING 子句中提供一个值。

AS 关联名称
为源值指定关联名称。 相关名称用于限定源值列的引用。
column-name
指定列名。 当指定关联名称时,也可以指定列名称 ,为赋值操作中的源值列命名。 如果指定了列列表,则源值中的每一列都必须有一个列列表中的名称。
更改结束
更改开始ON 搜索条件更改结束
更改开始指定用于确定表引用 或源值中的行是否与目标表中的行匹配的谓词。

搜索条件中的每个列名必须指明目标表或视图的列、表引用源值。 如果列名在目标值和源值中均存在,则必须限定列名。

更改开始从逻辑上讲,使用 ON 搜索条件在目标表与表引用 (或源值 )之间执行右连接。 对于搜索条件为 true 的连接结果表的行,执行指定的更新或删除操作。 对于搜索条件的结果不为 true 的连接结果表的行,执行指定的插入操作。更改结束

子查询不允许出现在ON子句的搜索条件中。 ON子句的搜索条件不能包含使用聚合函数或非确定性标量函数的表达式。

ON子句的搜索条件不得包含包含全选(fullselect)的IN谓词,也不得包含包含全选(fullselect)的量化谓词。

更改结束
更改开始匹配条件更改结束
更改开始

FL 500 指定 修改操作信号语句执行的条件。 每个匹配条件都按照规格进行评估。

更改开始如果未指定 NOT ATOMIC 子句,则在后续匹配条件中不会考虑匹配条件求值为真的记录。 有关详细信息,请参阅 MERGE 语句的规则更改结束

匹配的

指示对ON搜索条件为真的行执行的操作。 在THEN子句之后只能指定UPDATE、DELETE或信号语句

更改开始如果指定了 NOT ATOMIC 子句或 USING 源值 ,则 WHEN MATCHED 的指定次数不得超过一次。 有关详细信息,请参阅 MERGE 语句的规则更改结束

搜索条件
指定要对匹配 ON 搜索条件的行应用的进一步搜索条件,以便在 THEN 之后执行操作。 搜索条件中不得包含包含全选(fullselect)的IN谓词,也不得包含包含全选(fullselect)的量化谓词。
NOT MATCHED

指示对ON搜索条件为假或未知的行或目标表为空的行执行的操作。 在THEN子句之后只能指定INSERT或信号语句 ,且不能引用目标表的列。

更改开始如果指定了 NOT ATOMIC 子句或 USING 源值 ,则 WHEN NOT MATCHED 的指定次数不得超过一次。 有关详细信息,请参阅 MERGE 语句的规则更改结束

搜索条件
指定要对与 ON 搜索条件不匹配的行应用的进一步搜索条件,以便在 THEN 之后执行操作。 搜索条件不能包含目标表的列。
更改结束
更改开始然后进行修改操作更改结束
更改开始FL 500指定匹配条件评估为真时要执行的操作。
update-operation
指定当匹配条件为真时执行的更新操作。
UPDATE
引入更新操作。

更改开始启用扩展指标后,源表中的列不得在一次修改操作中被多次引用。 使用 EXTENDEDINDICATOR(YES) 或为 MERGE 语句指定 WITH EXTENDED INDICATORS 准备属性时,将启用扩展指示符。更改结束

当指定了 NOT ATOMIC CONTINUE ON SQLEXCEPTION,或者未指定 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句,但指定了源值 (VALUES) 时,同一语句中后续源行对源行进行的更新可能会覆盖对源行的更新。 更新是累积性的。

MERGE语句中的更新操作不会重置表中的AREO*状态。

SET
引入对列名的赋值。
assignment-clause
FL 500 指定列更新列表。

如果指定了 row-fullselect则row-fullselect结果中的列数必须与指定的列名数一致。 如果未指定行全选 ,则表达式、NULL和DEFAULT关键字的数量必须与指定的列名数量匹配。

column-name
标识要更新的列。 列名必须标识指定表或视图的列,且该列必须可更新。 列不能是生成的列,也不能是视图中的列,而视图是从标量函数、常数或表达式派生的。 列名也可以识别包含的列。 同一列名不能被指定多次。 视图列与视图中的另一列源自同一列,可以更新,但无法在同一MERGE语句中更新这两列。

只有在MERGE语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,才会处理包含列的分配。 必须至少有一个赋值子句指定非包含列的列名

表达式
指定列的新值。 表达式是指表达式中描述的任何类型的表达式。 表达式中不能包含聚合函数。

表达式可以包含表名 、视图名表引用源值的列引用。 对于每行更新,表达式中目标列的值是更新前该行中该列的值。 表达式不能包含对包含列的引用。

更改开始如果 expression 是对源表单列的引用,则源表列值可能已用扩展指示值指定。 扩展指标值的效果适用于赋值条款的相应目标列。更改结束

更改开始启用扩展指标后,如果表达式比以下引用更复杂,则不得使用 DEFAULT (-5) 或 UNASSIGNED (-7) 的扩展指标值:更改结束

  • 源表的一列
  • 单个主变量
缺省值
指定列的默认值。 只能对具有缺省值的列指定 DEFAULT。 更改开始不得为 ROWID 列指定 DEFAULT。更改结束 分配的值取决于列的定义方式。 有关默认值的更多信息,请参阅 CREATE TABLE语句中DEFAULT子句的描述。

更改开始必须为定义为 GENERATED ALWAYS 的列指定 DEFAULT。 可以为定义为 GENERATED BY DEFAULT 的列指定有效值。更改结束

NULL
指定空值作为列的新值。 仅对可空列指定 NULL。
row-fullselect
指定返回单行的全查询。 列值被分配给每个对应的列名。 如果fullselect没有返回任何行,则将空值分配给每一列;如果任何要更新的列不能为空,则会发生错误。

如果全选指的是要更新的列,则全选中的该列的值是该行更新前的值。

delete-operation
指定对匹配条件为真的行执行的删除操作。
删除
引入删除操作。
insert-operation
指定对匹配条件为真的行执行插入操作。
INSERT
指定用于插入操作的列名和行值表达式列表。
行值表达式中行的数值必须与插入列列表中的名称数量相等。 第一个值被插入列表的第一列,第二个值被插入第二列,以此类推。
列名 ,...)
指定插入值的列。 每个名称都必须标识表或视图的列。 同一列不能被标识多次。

更改开始如果未启用扩展指标,就不能识别不可更新的视图列。 如果扩展指示变量未启用,且插入操作的对象是具有不可更新列的视图,则必须指定列名列表,且该列表不得包含这些列。 有关视图中可更新列的解释,请参阅 CREATE VIEW 语句更改结束

如果列名列表中没有指定包含的列,则包含的列的值将设置为空。 列列表不能只包含已包含的列。

不能指定不接受插入值的视图列。 不能在由以下项目之一派生的视图列中插入值:

  • 常数、表达式或标量函数
  • 基础表的同一列与视图的同一列

如果操作的对象是包含不能接受插入值的列的视图,则必须指定列名列表,且该列表不能指定这些列。

省略列列表隐式指定了列表,其中表格(未定义为隐式隐藏)或视图的每一列均从左到右依次标识。 此列表是在报表编制时创建的,因此不包括报表编制后添加的列。

介绍要插入的一行或多行数值。
表达式
指定一个不包含目标列名的表达式。 如果表达式是一个宿主变量,则该宿主变量可以包含一个指示变量,或者,如果是宿主结构,则可以包含一个指示数组。 更改开始启用扩展指标后,如果表达式比以下引用更复杂,则不得使用 DEFAULT (-5) 或 UNASSIGNED (-7) 的扩展指标值:更改结束更改开始
  • 源表的一列
  • 单个主变量
  • 正在显式转换的主变量
更改结束
此外,在以下两种情况下可以使用CAST规范:
  • 目标列定义为可空。
  • 目标列定义为非空且默认值为非空,CAST规范的源是一个单一的主机变量,且主机变量的数据属性(数据类型、长度、精度和比例)与CAST规范的结果相同。
缺省值
指定列的默认值。 DEFAULT 仅适用于具有默认值的列。 赋值取决于列的定义方式。 有关默认值的更多信息,请参阅 CREATE TABLE语句INSERT语句中DEFAULT子句的描述。

如果列在包含列列表中指定,则列值设置为空。

对于定义为“始终生成”的列,必须指定默认值。 可以为定义为“默认生成”的列指定有效值。

NULL
指定空值作为列值。 仅对可空列指定 NULL。
更改结束
更改开始信号声明更改结束
更改开始指定要执行的 SIGNAL 语句,以便在匹配条件求值为 true 时返回错误。更改结束
更改开始ELSE IGNORE更改结束
更改开始FL 500指定不对匹配条件评估为 true 的记录采取任何操作。 如果忽略了 table-reference 的所有行,则会返回警告。更改结束
非原子继续SQLEXCEPTION

输入的数据行将分别进行处理。 对于每行源数据,都会处理任何语句级别触发器,转换表包含已处理的单独行。 当遇到错误且此选项生效时,处理将继续,但某些指定的行将不会被处理。 在这种情况下,如果在基础表上定义了适当的触发器,则语句级触发器将仅针对成功处理的行激活。

无论哪个源行出现故障,MERGE语句都不会撤销该语句对数据库所做的任何更改。 将尝试合并失败行之后的行。 然而,最小原子性至少是单个源行的原子性(也就是说,部分合并无法完成),包括可能因MERGE语句而激活的任何触发器。

更改开始虽然为了便于阅读,文档有时会使用 "NOT ATOMIC 子句 "的缩写,但 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句在使用时必须始终完全指定。更改结束

更改开始如果指定了 NOT ATOMIC 子句,则不得指定表引用有关详细信息,请参阅 MERGE 语句的规则更改结束

QUERYNO 整数
指定在EXPLAIN输出和跟踪记录中使用的SQL语句编号。 该数字用于计划表中 QUERYNO 列,其中包含有关此 SQL 语句的信息。 这个数字也用于 SYSIBM.SYSSTMT 和 SYSIBM.SYSPACKSTMT 目录表的QUERYNO列。

如果未指定QUERYNO,则与SQL语句关联的数字是预编译期间分配的语句编号。 因此,如果应用程序被修改并预编译,语句编号可能会发生变化。

更改开始

MERGE语句规则

FL 500如果指定了表格编号 ,则适用以下规则:

  • 一个MERGE语句中可以指定多个修改操作 (更新操作删除操作插入操作 )或信号语句
  • 只能对目标中的每一行执行一次操作。 目标中的行只能与表格引用结果表中的行匹配。 嵌套的SQL操作(RI或触发器,除了INSTEAD OF触发器)不能将目标表(或同一表层次结构中的表)指定为UPDATE、DELETE、INSERT或MERGE语句的目标。
  • MERGE语句插入的行也不能通过该MERGE语句进行更新。 在执行MERGE语句之前,不会尝试更新目标中不存在的行。
  • 如果在执行MERGE语句时出错,则整个语句将被回滚。

如果指定了NOT ATOMIC 子句1 ,或者省略了NOT ATOMIC子句但指定了USING 源值 (VALUES),则适用以下规则:

  • MERGE语句可以包含一个更新操作和一个插入操作
  • 从源行更新的行可能会受到同一语句中后续源行更新的影响。 更新是累积性的。
  • 当指定了 NOT ATOMIC CONTINUE ON SQLEXCEPTION 时,源数据行将单独处理。 在处理每行源数据时,MERGE语句中任何对特殊寄存器、序列表达式和函数的引用都会被计算。 在处理每行源数据时,语句级触发器被激活。
  • 如果在一行源数据操作过程中出现一个或多个错误,处理将继续进行。 发生错误时正在处理的行不会被插入或更新。 执行继续进行,下一行将被处理,在执行多行MERGE语句期间所做的任何其他更改都不会被撤销。 然而,处理单个行是一个原子操作。
  • 更改开始以下条款不得指定:
    • table-reference
    • 更改开始包含列名列表的关联条款更改结束
    • AND search-condition
    • delete-operation
    • SIGNAL
    • ELSE IGNORE
    • row-fullselect
    更改结束
  • WHEN MATCHED 条款不能重复出现。
  • WHEN NOT MATCHED 条款不能重复出现。
有关影响MERGE语句的更新、插入或删除部分的其他规则,请参阅以下主题中相应语句描述的规则部分:
更改结束

备注 MERGE

更改开始NOT ATOMIC 子句或 USING 源值的注意事项更改结束
更改开始

FL 500当指定了NOT ATOMIC 条款1 ,或者未指定NOT ATOMIC条款,但指定了 USING source-valuesVALUES 时,不得指定以下条款:

  • table-reference
  • 更改开始包含列名列表的关联条款更改结束
  • AND search-condition
  • delete-operation
  • SIGNAL
  • ELSE IGNORE
  • row-fullselect

以下规则也适用于这种情况:

  • WHEN MATCHED 条款不能重复出现。
  • WHEN NOT MATCHED 条款不能重复出现。
提示:
  1. 虽然为了便于阅读,文档有时会使用“非原子性条款”的缩写,但使用 NOT ATOMIC CONTINUE ON SQLEXCEPTION 条款时必须始终完整地指明其含义。
更改结束
更改开始非原子 MERGE 语句的逻辑处理顺序更改结束
更改开始FL 500对于非原子 MERGE 语句(包括 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句的 MERGE 语句,或未指定 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句但指定了源值(VALUES)的 MERGE 语句),将独立处理每条源记录,就像为每条源记录执行单独的 MERGE 语句一样。 例如,当更新目标行时,导致更新目标行的源行会激活所有触发器(包括语句级触发器)。 因此,如果更新了五行,则任何更新触发器(包括语句级更新触发器)都会激活五次。

对于非原子MERGE语句,每行的逻辑处理顺序如下:

  1. 从源和目标中确定要处理的行。
  2. 使用 ON 子句将这些行分类为 MATCHED 或 NOT MATCHED。
  3. 评估任何赋值语句插入操作中的任何表达式。
  4. 对适用行应用修改操作由修改操作触发的触发器将针对修改操作执行。 即使没有满足修改操作的行,语句级触发器也会被激活。
更改结束
更改开始原子 MERGE 语句的逻辑处理顺序更改结束
更改开始FL 500对于原子 MERGE 语句(未指定 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句),源记录的处理方式与每个 WHEN 子句处理一组记录的方式相同。 因此,如果更新了五行,则任何行级更新触发器都会激活五次。 此外 ,n个语句级更新触发器被激活,其中 n 是包含UPDATE的WHEN子句的数量,包括任何包含UPDATE的WHEN子句,这些子句没有处理任何源行。

对于原子MERGE,逻辑处理顺序如下:

  1. 确定要从源和目标中处理的一组行。 如果此语句中使用了当前日期、当前时间或当前时间戳等特殊寄存器,则整个语句只会进行一次时钟读取。
  2. 使用 ON 子句将这些行分类为 MATCHED 或 NOT MATCHED。
  3. 评估任何匹配条件 ,在WHEN子句中。
  4. 评估任何赋值语句插入操作中的任何表达式。
  5. 执行每个信号语句
  6. 按照规格说明的顺序,对适用行应用每个修改操作。 每次修改操作所激活的触发器都会为修改操作执行。 即使没有满足修改操作的行,语句级触发器也会被激活。 每次修改操作都会影响后续修改操作的触发器和参照约束。
更改结束
触发因素
MERGE语句可能会激活触发器。 触发器可能会根据源数据值执行其他语句或引发错误条件。 更新或插入操作之前,更新或插入操作之前立即触发。

如果源行导致插入,则插入操作完成后,任何插入后触发器都将激活。

如果源行导致更新,则所有更新操作完成后,任何更新后触发器都将激活。

更改开始如果源记录导致删除,则会在所有删除操作完成后激活任何删除后触发器。更改结束

更改开始更新行数更改结束
更改开始FL 500 执行 MERGE 语句后,SQL 诊断区(或 SQLCA 的 SQLERRD(3))中的 ROW_COUNT 语句信息项是 MERGE 语句操作的行数,不包括由 ELSE IGNORE 子句标识的行。 ROW_COUNT项和SQLERRD(3)不包括由于触发器而操作的行数。

有关ROW_COUNT的描述,请参阅 GET DIAGNOSTICS语句。 有关SQLCA的描述,请参阅 SQL通信区(SQLCA )。

更改结束
SQLCA和获取诊断信息注意事项
GET DIAGNOSTICS语句可以在MERGE语句之后立即使用,以检查在合并操作期间哪些输入行失败。 GET DIAGNOSTICS语句信息项NUMBER表示出现问题的数量。 GET DIAGNOSTICS状态信息项 DB2_ROW_NUMBER 指示导致错误的输入源行。
插入操作中无列列表的合并注意事项
作为插入操作的一部分,没有指定列列表的MERGE语句不包括隐含隐藏的列。 因此,此类列必须具有定义的默认值。
当指定NOT ATOMIC子句或省略NOT ATOMIC子句并指定源值 (VALUES)时,DRDA的注意事项

Db2 Connect 9.1 版本及更高版本支持MERGE语句。 该支持仅适用于CLI,不支持嵌入式静态SQL。

当您在 Db2 for z/OS® 请求者上运行MERGE语句时,可能会出现请求者不知道源表中行数的情况。 这种情况包括以下几种情况:

  • 对于静态或动态的MERGE语句,对于 FOR n ROWS 子句, n 包含一个常量值。
  • 对于动态MERGE语句,在EXECUTE语句的USING子句中指定了宿主变量。

对于这两种情况,如果源表中的行数未知,请求者可能会向服务器发送超出所需的数据。 处理行的数量是正确的,因为服务器知道要处理的正确行数。 然而,性能可能会受到不利影响。 请考虑以下示例:

...long serial num [10];
struct { short len;
char data [18];
       }
name[20]...
EXEC SQL 
MERGE INTO T1
  USING (VALUES (:serial_num, :name))
  FOR 5 ROWS...

当请求者运行此语句时,合并的行数(5)未知。 因此,请求者向服务器发送了10个 serial-name and name 的值,因为10是最小的主变量数组的大小,因此也是合并时不会导致错误的最大行数。

请执行以下操作,以尽量减少性能问题:

  • 避免在MERGE语句的FOR n ROWS子句中使用数字常量。 对于静态MERGE语句,避免使用数字常量可以确保请求者知道 n的值
  • 对于动态MERGE语句,请在EXECUTE语句中使用USING DESCRIPTOR子句,而不是 USING宿主变量子句。 如果在使用描述符的语句中使用 USING DESCRIPTOR 子句,则必须在描述符中指定 n 的值。
  • 如果上述方法均不可用,请执行以下操作:
    • 将宿主变量数组的大小尽可能减小,或者在描述符中声明宿主变量数组的大小为n。 此操作避免了将许多未使用的宿主变量数组条目发送到服务器。
    • 确保将不同长度的字符串数组初始化为0(零)。 这样做可以减少发送到服务器的数据量。
    • 确保十进制主机变量数组被初始化为有效值。 这样做可以避免请求者在遇到无效的小数数据时发送负SQLCODE。
更改开始扩展指标用途更改结束
更改开始启用扩展指标后,除正值和 0(零)至 -7 外,不得指定其他指标值。 DEFAULT 和 UNASSIGNED 扩展指示符值不得出现在不支持它们的上下文中。更改结束
更改开始扩展指示符更改结束
更改开始在 MERGE 语句的更新操作中:
  • UNASSIGNED的扩展指示值与在语句中未指定该值的效果相同。
  • 更改开始不得为行开始、行结束、事务开始-ID 或生成表达式列指定 DEFAULT 扩展指示符值。更改结束
  • 不可将未分配的扩展指示器值分配给所有目标列。

在MERGE语句的插入操作中,UNASSIGNED的扩展指示器值具有将列设置为默认值的效果。

更改结束
扩展指标和更新触发器
如果目标列的扩展指示器值为未分配,则该列被视为未更新。 该列被视为在目标表上定义的任何更新触发器的 OF 列名列表中未指定。
扩展指示器和插入触发器
插入触发器的激活不受扩展指示变量的影响。 假设隐式或显式列列表中的所有列都分配了未分配或默认的扩展指示符值。 然后,假设尝试插入操作,其中所有列都分配给各自的默认值。 如果操作成功,插入触发器将被激活。
插入操作期间表空间数据压缩
如果表空间定义为压缩,且数据插入到表空间中的表中,则第一行数据将以未压缩的形式存储。 当由 Db2 确定的数据量被插入到表中时,压缩字典将被创建并存储在表空间中。 在创建词典后插入到表格中的行使用压缩词典进行压缩存储。
系统时间段时态表
当对系统周期临时表处理MERGE语句时,行的影响方式与调用特定数据更改操作的影响方式相同。
支持存档的表格
考虑MERGE语句的目标是启用存档的表,且合并操作包括插入或更新操作的情况。 在这种情况下,所涉及的行会受到与直接在表上执行插入或更新操作相同的影响。

更改开始当全局变量设置为 "Y "时,将启用存档的表作为目标引用的 MERGE 语句会返回错误。 更改结束

具有强制行和列访问控制的表格
有关启用行权限和列掩码如何影响 MERGE 语句中的更新和插入操作的信息,请参阅 INSERT 和 UPDATE 语句信息。

MERGE语句示例

  • 更改开始FL 500 对于说明已更改的活动,更新 RECORDS 表中的说明。 对于新活动,请插入记录表。 RECORDS 表和 ACTIVITIES 表的主键都是 ACTIVITY。更改开始
    MERGE INTO RECORDS AR
     USING (SELECT ACTIVITY, DESCRIPTION FROM ACTIVITIES) AC
     ON (AR.ACTIVITY = AC.ACTIVITY)
     WHEN MATCHED THEN
      UPDATE SET
      DESCRIPTION = AC.DESCRIPTION
     WHEN NOT MATCHED THEN
      INSERT
      (ACTIVITY, DESCRIPTION)
      VALUES (AC.ACTIVITY, AC.DESCRIPTION);
    更改结束更改结束
  • 更改开始FL 500 使用 SHIPMENT 表,将行合并到 INVENTORY 表:对于匹配的行,按 SHIPMENT 表中的零件数增加数量;否则,在库存表中插入新零件编号的行。更改开始
    MERGE INTO INVENTORY AS IN
     USING (SELECT PARTNO, DESCRIPTION, COUNT FROM SHIPMENT
     WHERE SHIPMENT.PARTNO IS NOT NULL) AS SH
     ON (IN.PARTNO = SH.PARTNO)
     WHEN MATCHED THEN
      UPDATE SET
       DESCRIPTION = SH.DESCRIPTION,
       QUANTITY = IN.QUANTITY + SH.COUNT
     WHEN NOT MATCHED THEN
      INSERT
      (PARTNO, DESCRIPTION, QUANTITY)
      VALUES (SH.PARTNO, SH.DESCRIPTION, SH.COUNT);
    更改结束更改结束
  • 更改开始FL 500 使用 TRANSACTION 表,将记录合并到 ACCOUNT 表:根据账户 ID 更新交易集合中的余额,并从合并交易中插入尚未存在的新账户。更改开始
    MERGE INTO ACCOUNT AS A
     USING (SELECT ID, SUM(AMOUNT) SUM_AMOUNT FROM TRANSACTION
      GROUP BY ID) AS T
      ON A.ID = T.ID
     WHEN MATCHED THEN
      UPDATE SET
       BALANCE = A.BALANCE + T.SUM_AMOUNT
     WHEN NOT MATCHED THEN
      INSERT
      (ID, BALANCE)
       VALUES (T.ID, T.SUM_AMOUNT);
    更改结束更改结束
  • 更改开始FL 500 使用 TRANSACTION_LOG 表,将记录合并到 EMPLOYEE_FILE 表中:根据交易时间,用最新的 TRANSACTION_LOG 行更新电话和办公室,并插入最新的新 EMPLOYEE_FILE 行(如果该行尚未存在)。更改开始
    MERGE INTO EMPLOYEE_FILE AS E
     USING (SELECT EMPID, PHONE, OFFICE
      FROM (SELECT EMPID, PHONE, OFFICE,
      ROW_NUMBER() OVER (PARTITION BY EMPID
      ORDER BY TRANSACTION_TIME DESC) RN
      FROM TRANSACTION_LOG) AS NT
      WHERE RN = 1) AS T
      ON E.EMPID = T.EMPID
     WHEN MATCHED THEN
      UPDATE SET
       (PHONE, OFFICE) =
       (T.PHONE, T.OFFICE)
     WHEN NOT MATCHED THEN
      INSERT
      (EMPID, PHONE, OFFICE)
      VALUES (T.EMPID, T.PHONE, T.OFFICE);
    更改结束更改结束
  • 更改开始FL 500 更新 RECORDS 表中按 A 组组织的活动清单。 删除所有过期的活动,如果活动信息(描述和日期)有更改,请在记录表中更新。 对于即将开展的新活动,请插入记录表。 如果活动的日期未知,那么指示错误。 必须在“记录”表中注明活动日期。 每个组都有一个活动表。 例如,ACTIVITIES_GROUPA包含A组组织的全部活动,而RECORDS表则包含公司内不同组别即将组织的全部活动。 RECORDS表以(GROUP、ACTIVITY)作为主键,DATE为非空值。 所有活动表都将活动作为主键。 RECORDS 表中的 LAST_MODIFIED 列以 CURRENT TIMESTAMP 作为默认值。更改开始
    MERGE INTO RECORDS AR
     USING (SELECT ACTIVITY, DESCRIPTION, DATE, LAST_MODIFIED
      FROM ACTIVITIES_GROUPA) AC
      ON (AR.ACTIVITY = AC.ACTIVITY) AND AR.GROUP = 'A'
     WHEN MATCHED AND AC.DATE IS NULL THEN
      SIGNAL SQLSTATE '70001'
       SET MESSAGE_TEXT =
        AC.ACTIVITY CONCAT ' CANNOT BE MODIFIED. REASON: DATE IS NOT KNOWN'
     WHEN MATCHED AND AC.DATE < CURRENT DATE THEN
      DELETE
     WHEN MATCHED AND AR.LAST_MODIFIED < AC.LAST_MODIFIED THEN
      UPDATE SET
      (DESCRIPTION, DATE, LAST_MODIFIED) = (AC.DESCRIPTION, AC.DATE, DEFAULT)
     WHEN NOT MATCHED AND AC.DATE IS NULL THEN
      SIGNAL SQLSTATE '70002'
       SET MESSAGE_TEXT =
        AC.ACTIVITY CONCAT ' CANNOT BE INSERTED. REASON: DATE IS NOT KNOWN'
     WHEN NOT MATCHED AND AC.DATE >= CURRENT DATE THEN
      INSERT
       (GROUP, ACTIVITY, DESCRIPTION, DATE)
       VALUES ('A', AC.ACTIVITY, AC.DESCRIPTION, AC.DATE)
     ELSE IGNORE;
    更改结束更改结束
  • 更新记录表中活动的描述。 否则,请将活动及其描述插入“记录”表中。
    MERGE INTO RECORDS AR
      USING (VALUES (:hv_activity, :hv_description)
        FOR :hv_nrows ROWS)
        AS AC (ACTIVITY, DESCRIPTION)
      ON (AR.ACTIVITY = AC.ACTIVITY)
      WHEN MATCHED THEN UPDATE SET DESCRIPTION = AC.DESCRIPTION
      WHEN NOT MATCHED THEN INSERT (ACTIVITY, DESCRIPTION)
         VALUES (AC.ACTIVITY, AC.DESCRIPTION)
      NOT ATOMIC CONTINUE ON SQLEXCEPTION;
  • 使用交易数据将行合并到账户表中。 根据账户ID更新交易数据的余额,并在交易数据中插入尚不存在的新账户。
    MERGE INTO ACCOUNT AS A
      USING (VALUES (:hv_id, :hv_amount) 
        FOR 3 ROWS)
        AS T (ID, AMOUNT)
      ON (A.ID = T.ID)
      WHEN MATCHED THEN UPDATE SET BALANCE = A.BALANCE + T.AMOUNT
      WHEN NOT MATCHED THEN INSERT (ID, BALANCE) 
          VALUES (T.ID, T.AMOUNT)
      NOT ATOMIC CONTINUE ON SQLEXCEPTION;
  • 更新记录表中A组组织的活动列表。 如果活动存在于记录表中,且也按A组进行组织,则更新记录表中的活动信息(描述和上次修改的日期)。 在记录表中插入新的活动。
    -- hv_nrows = 3
    -- hv_activity(1) = 'D'; hv_description(1) = 'Dance'; hv_date(1) = '03/01/07'
    -- hv_activity(2) = 'S'; hv_description(2) = 'Singing'; hv_date(2) = '03/17/07'
    -- hv_activity(3) = 'T'; hv_description(3) = 'Tai-chi'; hv_date(3) = '05/01/07'
    -- hv_group = 'A';
    -- note that hv_group is not an array. All 3 values contain the same values
    MERGE INTO RECORDS AR
      USING (VALUES (:hv_activity, :hv_description, :hv_date, :hv_group)
         FOR :hv_nrows ROWS)
         AS AC (ACTIVITY, DESCRIPTION, DATE, GROUP)
      ON AR.ACTIVITY = AC.ACTIVITY AND AR.GROUP = AC.GROUP
      WHEN MATCHED 
      THEN UPDATE SET (DESCRIPTION, DATE, LAST_MODIFIED)
                      = (AC.DESCRIPTION, AC.DATE, CURRENT TIMESTAMP)
      WHEN NOT MATCHED
      THEN INSERT (GROUP, ACTIVITY, DESCRIPTION, DATE, LAST_MODIFIED)
         VALUES (AC.GROUP, AC.ACTIVITY, AC.DESCRIPTION, AC.DATE, CURRENT TIMESTAMP)
      NOT ATOMIC CONTINUE ON SQLEXCEPTION;
  • 使用两个数组(CHARA和INTA)作为MERGE语句的输入。 对于匹配的行,列 COL2 设置为 CHARA 的单数;对于不匹配的行,列 COL2 设置为 INTA 的单数。更改开始
    CREATE TYPE INTARRAY AS INTEGER ARRAY[6];
    CREATE TYPE CHARARRAY AS CHAR(20) ARRAY[7];
    CREATE VARIABLE INTA AS INTARRAY;
    CREATE VARIABLE CHARA AS CHARARRAY;
    CREATE VARIABLE SI INT;
    SET CHARA = ARRAY['a', 'b', 'c'];
    SET INTA = ARRAY [1, 2, 3, 4, 5];
    CREATE TABLE T1 (COL1 CHAR(7), COL2 INT);
    INSERT INTO T1 VALUES ('abc', 10);
    MERGE INTO T1 AS A
     USING TABLE (VALUES ('rsk', 3 ) ) AS T (ID, AMOUNT)
     ON A.COL1 = T.ID
     WHEN MATCHED
      THEN UPDATE SET COL2 = CARDINALITY(CHARA)
     WHEN NOT MATCHED
      THEN INSERT (COL1, COL2 ) VALUES (T.ID, CARDINALITY(INTA));
    更改结束