南大通用GBase8s 常用SQL语句(167)

对目标表的限制

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

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

下列限制适用于 MERGE 语句的目标表。如果那个表有任何下列的属性,则 MERGE 操作返回错误。

  1. 目标不可为该源表所在同一表层级中的类型化表。
  2. 目标不可为“虚拟表接口”(VTI)表。
  3. 目标不可为 CREATE EXTERNAL TABLE 语句定义的对象。
  4. 目标不可在远程 GBase 8s 实例的数据库中。
  5. 目标不可为系统目录表。
  6. 目标不可为在其上定义启用的 INSTEAD OF 触发器的视图。
  7. 目标不可为只读视图。
  8. 目标不可为伪表(在系统数据库中的常驻内存的对象,比如 sysmaster 或 sysadmin 数据库)。
  9. 目标不可为同一 MERGE 语句的任何子查询的数据源,包括 ON 子句中的、SET 子句中的或 VALUES 子句中的子查询。
  10. 如果 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 操作的兼容性要求:

  1. 如果一个数据库符合 ANSI,则其他数据库必须也符合 ANSI。
  2. 如果一个数据库不符合 ANSI 但是用显式的事务日志记录,则其他数据库必须也支持显式的事务日志记录。
  3. 如果一个数据库不支持事务日志记录,则其他数据库也必须不支持。
  4. 两个数据库必须有相同的 NLSCASE 敏感性设置。

例如,分布式 MERGE 语句不可在区分大小的数据库中指定源表,而在创建为 NLSCASE INSENSITIVE 的数据库中指定目标表,不论表是否包括 NCHAR 或 NVARCHAR 列。

处理重复的行

在执行 MERGE 时,目标表中的同一行不可被更新或被删除一次以上。在执行了 MERGE 语句之前,请勿尝试更新或删除尚未存在的目标中的任何行。即,没有同一 MERGE 语句插入到目标内的行的更新或删除。

下列 MERGE 语句的示例使用事务表 new_sale 作为源表,从其来在事实表中插入或更新行。在此样例中的结合条件测试 new_sale.cust_id 列值与 sale.cust_id 列值是否相匹配。

MERGE INTO sale USING new_sale AS n

   ON sale.cust_id = n.cust_id

   WHEN MATCHED THEN UPDATE

      SET sale.salecount = sale.salecount + n.salecount

   WHEN NOT MATCHED THEN INSERT (cust_id, salecount)

      VALUES (n.cust_id, n.salecount);

要执行此 MERGE 语句,数据库服务器结合目标表和源表,并应用指定的相等条件来处理结合的结果:

  • 对于满足条件的行(因为 sale.cust_id 值与 new_sale.cust_id 值相匹配),MERGE 根据 SET 子句的指定,更新 sale.salecount 列值。
  • 对于不满足条件的行(因为在 sale 表中没有行有与 new_sale.cust_id 相同的 cust_id 值),MERGE 根据 VALUES 子句的指定,将包含 new_sale.cust_id 和 new_sale.salecount 值的新行插入 sale 表内。

对于先前示例中的 MERGE 语句,假设 sale 目标包含两条记录,而 new_sale 源表包含三条记录。

表 1. “sale”表中的记录

cust_id

sale_count

Tom

129

Julie

230

表 2. “new_sale”表中的记录

cust_id

sale_count

Tom

20

Julie

3

Julie

10

当通过指定表达式 sale.cust_id = new_sale.cust_id 作为匹配条件将 new_sale 合并至 sale 内时,MERGE 语句返回错误,因为它尝试超过一次更新 sale 目标表中的记录之一。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值