对 MERGE 的源表和目标表的限制

哪些表对象可为 MERGE 语句的源或目标,这取决于该表对象的属性,以及发出 MERGE 语句的对象所持有的访问权限。

对于当前会话连接到的数据库,目标表必须为本地的,但您可指定一远程表作为源表,或在 UPDATA 操作的 SET 子句的子查询中,或在 INSERT 操作的 VALUES 子句的子查询中。

下列章节标识对源表和目标表的附加的限制。

对源表的限制

源对象可为 STANDARD、RAW、TEMP、EXTERNAL 或集合派生的表或视图的名称或同义词。它可与目标对象在同一数据库中,或在本地 GBase 8s 实例的不同数据库中,它或可为由不同的 GBase 8s 实例管理的远程表。

如果源是由查询的结果所定义的集合派生的表,则 USING 子句可声明派生的列的名称,MERGE 语句的 SET 和 VALUES 子句可引用这些列。

发出 MERGE 语句的用户必须持有对源对象的数据库的 Connect 访问权限(或更高的权限),其必须还持有对源对象的 Select 权限(或更高的权限)。可分别地授予该用户这些访问权限,或该用户作为 PUBLIC 组的成员而持有它们,或如果当前的或缺省的角色或 PUBLIC 持有那些权限,则可通过用户的角色持有权限。

如果源对象或其任意列受到基于标签的安全策略保护,则发出 MERGE 语句的用户必须有提供其读取该源对象的充足凭证的安全标签(或必须持有安全策略豁免)。如果该用户的凭证不足以读取受保护的列,根据标准基于标签的访问控制(LBAC)规则,则该 MERGE 语句仅可处理该源数据的一个子集。如果此子集为空,则 MERGE 语句不可从源对象向目标表内插入任何值。

下列限制适用于源表对象:
  • 源不可为在其上定义启用的 SELECT 触发器的视图。
  • 源不可为与目标表在同一表层级中的类型化表
  • 在 Delete 合并中,源不可与目标有孩子表关系,由启用的引用约束定义,如果以 ON DELETE CASCADE 关键字定义了那个约束的话。(然而,孩子表关系不影响 Delete 合并,除非目标表约束指定级联删除。)

对目标表的限制

目标表对象必须在当前会话连接到的同一 GBase 8s 实例的数据库中。它可为 STANDARD、RAW 或 TEMP 表,或可更新的视图的名称或同义词。如果目标在表层级内为可更新的,则 Delete 子句还删除该目标表的所有子表中相应的行。

发出 MERGE 语句的用户必须持有对目标对象的数据库的 Connect 访问权限(或更高的权限),且必须持有对目标对象的 Insert 权限和 Update 或 Delete 权限,如果 MERGE 语句包括相应的 Insert、Update 或 Delete 子句的话。

下列限制适用于 MERGE 语句的目标表。如果那个表有任何下列的属性,则 MERGE 操作返回错误。
  • 目标不可为该源表所在同一表层级中的类型化表。
  • 目标不可为“虚拟表接口”(VTI)表。
  • 目标不可为 CREATE EXTERNAL TABLE 语句定义的对象。
  • 目标不可在远程 GBase 8s 实例的数据库中。
  • 目标不可为系统目录表。
  • 目标不可为在其上定义启用的 INSTEAD OF 触发器的视图。
  • 目标不可为只读视图。
  • 目标不可为伪表(在系统数据库中的常驻内存的对象,比如 sysmastersysadmin 数据库)。
  • 目标不可为同一 MERGE 语句的任何子查询的数据源,包括 ON 子句中的、SET 子句中的或 VALUES 子句中的子查询。
  • 如果 MERGE 语句包括 DELETE 子句,则目标不可与源表有父表关系,如果通过指定 ON DELETE CASCADE 关键字的启用的引用约束定义此关系的话。

对综合的行长度的限制

MERGE 语句中的源表和目标表不可有合计综合的行长度(= 源表的行大小 + 目标表的行大小)大于 32,767 字节。否则,MERGE 语句失败并报错,如下例所示:
CREATE TABLE t1 
       (f1  INT, 
        f2  VARCHAR(10),
        lv1 LVARCHAR(5000),
        lv2 LVARCHAR(4000),
        lv3 LVARCHAR(8000));
CREATE TABLE t2 
       (f1  INT, 
        f2  VARCHAR(10),
        lv1 LVARCHAR(5000),
        lv2 LVARCHAR(4000),
        lv3 LVARCHAR(8000));

INSERT INTO t1 (f1,f2) VALUES (1,'t1 1');
INSERT INTO t1 (f1,f2) VALUES (2,'t1 2');
INSERT INTO t1 (f1,f2) VALUES (3,'t1 3');
INSERT INTO t1 (f1,f2,lv1) VALUES (7,'t1 7',
   'loooooooooooooooooong');

INSERT INTO t2 (f1,f2) VALUES (3,'t2 3');
INSERT INTO t2 (f1,f2) VALUES (4,'t2 4');
INSERT INTO t2 (f1,f2) VALUES (5,'t2 5');
INSERT INTO t2 (f1,f2) VALUES (6,'t2 6');

MERGE INTO t2 AS o  USING t1 AS n ON o.f1 = n.f1 
   WHEN NOT MATCHED THEN INSERT ( o.f1,o.f2)
      VALUES ( n.f1,n.f2);
上述 MERGE 语句失败,因为源和目标表的行长度的总和超出 32,767 字节的上限。
对于仅包括 INSERT 子句(而既没有 DELETE 子句也没有 UPDATE 子句)的 MERGE 操作,您可以通过用 INSERT INTO . . . SELECT 语句代替 MERGE 语句来绕过此行长度限制。对于上述 MERGE 示例中相同的表和数据值,下列 INSERT 语句运行成功:
INSERT INTO t2(f1, f2) 
   SELECT t1.f1, t1.f2 FROM t1 
      WHERE NOT EXISTS 
         (SELECT f1, f2 FROM t2 
            WHERE t2.f1 = t1.f1);

INSERT INTO t2(f1,f2) 
   SELECT t1.f1, t1.f2 FROM t1 
      LEFT JOIN t2 ON t1.f1 = t2.f1
         WHERE t2.f1 IS NULL; 
在两个 INSERT INTO . . . SELECT 操作之后,表 t2 包含前一个 MERGE 示例受限无法返回的行大小。

对分布式 MERGE 语句的限制

如果源表与目标表不在同一数据库中,则两个数据库都必须满足对跨数据库和跨服务器 DML 操作的兼容性要求:
  • 如果一个数据库符合 ANSI,则其他数据库必须也符合 ANSI。
  • 如果一个数据库不符合 ANSI 但是用显式的事务日志记录,则其他数据库必须也支持显式的事务日志记录。
  • 如果一个数据库不支持事务日志记录,则其他数据库也必须不支持。
  • 两个数据库必须有相同的 NLSCASE 敏感性设置。
例如,分布式 MERGE 语句不可在区分大小的数据库中指定源表,而在创建为 NLSCASE INSENSITIVE 的数据库中指定目标表,不论表是否包括 NCHAR 或 NVARCHAR 列。