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 トリガ

たとえば、次の文では、Policy テーブルに対する挿入を追跡する BEFORE INSERT トリガを作成し、リモート・データベースに適切なデータが含まれることを保証します。

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 トリガ

次の文では、Policy テーブルからの削除を追跡する BEFORE DELETE トリガを作成します。

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 式の 2 番目の部分は、INSERT 文から取得した、顧客と取り引きする新しい営業担当者の rep_key 値です。

BEFORE DELETE トリガ内のサブクエリは、複数の値を返します。

...
SELECT rep_key
FROM Policy
WHERE cust_key = OldRow.cust_key
AND rep_key <> OldRow.rep_key
...
  • サブクエリは、Policy テーブルから rep_key の値を取得します。削除される値 (AND rep_key <> OldRow.rep_key) を除き、移動される顧客 (WHERE cust_key = OldRow.cust_key) と取り引きする営業担当者全員のプライマリ・キー値が、その値に含まれます。

    サブスクリプション・クエリの結果セットには、削除に続くローを受信する営業担当者と一致した値のすべてが含まれている必要があります。

注意
  • Customers テーブルのデータは、(プライマリ・キーの値などによって) 個々のサブスクライバと関連付けられることはなく、複数のサブスクライバ間で共有されます。このため、レプリケーション・メッセージ間の複数のリモート・サイトでデータが更新される可能性があり、レプリケーションの競合が発生することがあります。(特定のユーザだけに Customers テーブルの更新権を付与するなどの方法で) パーミッションを使用するか、データベースに RESOLVE UPDATE トリガを追加してプログラム上で競合を処理することによって、この問題に対処できます。

  • Policy テーブル上の更新については、ここでは説明していません。そのような操作は避けるか、例で示したように、BEFORE INSERT と BEFORE DELETE の各トリガの機能を組み合わせる BEFORE UPDATE トリガを作成する必要があります。