Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 11.0.1 (中文) » SQL Remote » SQL Remote 复制设计 » SQL Remote 复制设计和设置 » 使用有交集分区

 

在预订者之间重新指派行时保持参照完整性

若要取消某客户与某销售代表间的销售关系,应删除 Policy 表中的某行。在本示例中,Policy 表更改被正确复制给以前的销售代表。但未对 Customers 表进行任何更改,因此也没有将 Customers 表的任何更改复制给以前的销售代表。

在没有触发器的情况下,这将使预订者在 Customers 表中留下不正确的数据。在将新行添加到 Policy 表时也会产生此类问题。

使用触发器解决该问题

解决方法是编写可在 Policy 表被更改时触发的 BEFORE 触发器。这些特殊的触发器不会对数据库表进行任何更改,但会在 SQL Remote 用于维护预订者数据库中的数据的事务日志中创建一个条目。

BEFORE INSERT 触发器

例如,以下语句创建一个 BEFORE INSERT 触发器,该触发器可跟踪对 Policy 表执行的插入操作并确保远程数据库包含正确的数据。

CREATE TRIGGER InsPolicy
BEFORE INSERT ON Policy
REFERENCING NEW AS NewRow
FOR EACH ROW
BEGIN
   UPDATE Customers
   PUBLICATION SalesRepData
   SUBSCRIBE BY (
      SELECT rep_key
      FROM Policy
      WHERE cust_key = NewRow.cust_key
      UNION ALL
      SELECT NewRow.rep_key
   )
   WHERE cust_key = NewRow.cust_key;
END;
BEFORE DELETE 触发器

以下语句创建一个 BEFORE DELETE 触发器,该触发器可跟踪对 Policy 表执行的删除操作:

CREATE TRIGGER DelPolicy
BEFORE DELETE ON Policy
REFERENCING OLD AS OldRow
FOR EACH ROW
BEGIN
   UPDATE Customers
   PUBLICATION SalesRepData
   SUBSCRIBE BY (
      SELECT rep_key
      FROM Policy
      WHERE cust_key = OldRow.cust_key
      AND Policy_key <> OldRow.Policy_key
   )
   WHERE cust_key = OldRow.cust_key;
END;

UPDATE PUBLICATION 语句的 SUBSCRIBE BY 子句包含一个子查询,该子查询可以是多值的。

多值子查询

UPDATE PUBLICATION 语句的 SUBSCRIBE 子句中的子查询是一个 UNION 表达式,并且该子查询可以是多值的:

...
SELECT rep_key
FROM Policy
WHERE cust_key = NewRow.cust_key
UNION ALL
SELECT NewRow.rep_key
...
  • UNION 的第一部分是与该客户有业务关系的现有销售代表的集合,这是从 Policy 表获取的。

    预订查询的结果集肯定是接收该行的所有销售代表,而不仅仅是新销售代表。

  • UNION 的第二部分是与该客户有业务来往的新销售代表的 rep_key 值,该值是从 INSERT 语句获取的。

BEFORE DELETE 触发器中的子查询是多值的:

...
SELECT rep_key
FROM Policy
WHERE cust_key = OldRow.cust_key
AND rep_key <> OldRow.rep_key
...
  • 该子查询从 Policy 表中获取 rep_key 值。这些值包含与要转移的客户有业务来往的所有销售代表的主键值 (WHERE cust_key = OldRow.cust_key),要删除的销售代表除外 (AND rep_key <> OldRow.rep_key)。

    预订查询的结果集肯定是执行删除操作后所有与接收该行的销售代表匹配的值。

注意
  • Customers 表中的数据不是通过单个预订者(例如通过主键值)标识的,而是由多个预订者共享。这可能导致数据在多个远程站点上的各复制消息之间更新,进而造成复制冲突。解决此问题的方法是,通过权限解决(例如,只授予某些用户更新 Customers 表的权限),或者是向数据库添加 RESOLVE UPDATE 触发器以按编程方式处理冲突。

  • 这里未介绍对 Policy 表的更新。应避免进行这些更新,或必须创建一个结合了示例中介绍的 BEFORE INSERT 和 BEFORE DELETE 两个触发器功能的 BEFORE UPDATE 触发器。