MERGE 语句
FL 500 MERGE 语句使用源数据(表引用或指定输入数据的结果)更新目标(表或视图)。 目标中与输入数据匹配的行可以按指定方式删除或更新,目标中不存在的行可以插入。 如果视图上没有定义“代替”触发器,则更新、删除或插入视图中的行,也会更新、删除或插入视图所基于的表中的行。
调用 MERGE
此语句可嵌入应用程序中或者以交互方式发出。 它是可动态准备的可执行语句。
授权 MERGE
以下定义的特权集所包含的特权必须至少包括以下特权之一:
- SYSADM 权限
- 对表的所有权
- DATAACCESS 权限
- 如果搜索条件包含对表或视图某一列的引用,则引用表或视图的 SELECT 权限
- 如果指定了删除操作,则表或视图的删除权限
- 如果指定了插入操作,则表或视图的插入权限
- 如果指定了更新操作,则至少需要以下权限之一:
- 表或视图的更新权限
- 每列的更新权限
- 如果分配条款的右侧包含对表格或视图某一列的引用,则引用表格或视图的 SELECT 权限
如果数据库是隐式创建的,则数据库权限必须位于隐式数据库或 DSNDB04 上。
如果插入操作或赋值子句包含子查询,则权限集所拥有的权限必须至少包括以下权限之一:
- SYSADM 权限
- 子查询中确定的每个表或视图的 SELECT 权限
- 子查询中确定的表或视图的所有权
- DATAACCESS 权限
权限设置:
如果语句嵌入到应用程序中,权限集就是计划或软件包所有者所拥有的权限。 如果语句是动态编写的,则权限集由生效的 DYNAMICRULES 行为(运行、绑定、定义或调用)决定, 如表 1 所示。 (有关这些行为的更多信息,包括决定这些行为的 DYNAMICRULES 绑定选项值列表,请参阅授权 ID 和动态 SQL )
MERGE的语法
- 1 指定此条款的规则受NOT ATOMIC条款或USING条款中源值的影响。 更多信息,请参阅 MERGE语句规则。
相关条款:
包括列:
数据类型:
内置类型:
源值:
值-单行:
多行值:
- 1 对于静态MERGE语句,如果未指定FOR n ROWS,则 values-multiple-row 被视为 values-single-row。 对于动态MERGE语句,不需要在MERGE语句中指定FOR n ROWS。 它可以在EXECUTE语句中指定,但不能同时在MERGE和EXECUTE语句中指定。
匹配条件:
- 1 指定此条款的规则受NOT ATOMIC条款或USING条款中源值的影响。 更多信息,请参阅 MERGE语句规则。
修改-操作:
- 1 指定此条款的规则受NOT ATOMIC条款或USING条款中源值的影响。 更多信息,请参阅 MERGE语句规则。
assignment-clause:
- 1 表达式、DEFAULT和NULL关键字的数量必须与列名称的数量一致。
- 2 SELECT列表中的列数必须与列名数一致。
- 3 指定此条款的规则受非原子性条款或具有源值的 “使用”条款的影响。 欲了解更多信息,请发送电子邮件至 MERGE语句规则。.
更新操作:
删除操作:
插入操作:
描述 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-name 或 view-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-row或VALUESvalues-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-variable 或 integer-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-conditiondelete-operationSIGNALELSE IGNORErow-fullselect

WHEN MATCHED条款不能重复出现。WHEN NOT MATCHED条款不能重复出现。

备注 MERGE
NOT ATOMIC 子句或 USING 源值的注意事项

FL 500当指定了NOT ATOMIC 条款1 ,或者未指定NOT ATOMIC条款,但指定了
USING source-values和VALUES时,不得指定以下条款:table-reference
包含列名列表的关联条款
AND search-conditiondelete-operationSIGNALELSE IGNORErow-fullselect
以下规则也适用于这种情况:
WHEN MATCHED条款不能重复出现。WHEN NOT MATCHED条款不能重复出现。
提示:- 虽然为了便于阅读,文档有时会使用“非原子性条款”的缩写,但使用
NOT ATOMIC CONTINUE ON SQLEXCEPTION条款时必须始终完整地指明其含义。

非原子 MERGE 语句的逻辑处理顺序
FL 500对于非原子 MERGE 语句(包括 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句的 MERGE 语句,或未指定 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句但指定了源值(VALUES)的 MERGE 语句),将独立处理每条源记录,就像为每条源记录执行单独的 MERGE 语句一样。 例如,当更新目标行时,导致更新目标行的源行会激活所有触发器(包括语句级触发器)。 因此,如果更新了五行,则任何更新触发器(包括语句级更新触发器)都会激活五次。对于非原子MERGE语句,每行的逻辑处理顺序如下:
- 从源和目标中确定要处理的行。
- 使用 ON 子句将这些行分类为 MATCHED 或 NOT MATCHED。
- 评估任何赋值语句和插入操作中的任何表达式。
- 对适用行应用修改操作。 由修改操作触发的触发器将针对修改操作执行。 即使没有满足修改操作的行,语句级触发器也会被激活。

原子 MERGE 语句的逻辑处理顺序
FL 500对于原子 MERGE 语句(未指定 NOT ATOMIC CONTINUE ON SQLEXCEPTION 子句),源记录的处理方式与每个 WHEN 子句处理一组记录的方式相同。 因此,如果更新了五行,则任何行级更新触发器都会激活五次。 此外 ,n个语句级更新触发器被激活,其中 n 是包含UPDATE的WHEN子句的数量,包括任何包含UPDATE的WHEN子句,这些子句没有处理任何源行。对于原子MERGE,逻辑处理顺序如下:
- 确定要从源和目标中处理的一组行。 如果此语句中使用了当前日期、当前时间或当前时间戳等特殊寄存器,则整个语句只会进行一次时钟读取。
- 使用 ON 子句将这些行分类为 MATCHED 或 NOT MATCHED。
- 评估任何匹配条件 ,在WHEN子句中。
- 评估任何赋值语句和插入操作中的任何表达式。
- 执行每个信号语句。
- 按照规格说明的顺序,对适用行应用每个修改操作。 每次修改操作所激活的触发器都会为修改操作执行。 即使没有满足修改操作的行,语句级触发器也会被激活。 每次修改操作都会影响后续修改操作的触发器和参照约束。

- 触发因素
- 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));
