次の例では、3 つのテーブル Customers、Contacts、SalesReps に、営業担当者と顧客間の対話に関する情報が格納されています。各営業担当者は、複数の顧客に対して販売活動を行います。連絡先が 1 箇所だけの顧客もいれば、複数ある顧客もいます。
テーブルの詳細については、Contacts、Customers、SalesReps テーブルの説明を参照してください。
営業担当者は、SalesRep テーブルのコピー、営業担当者に割り当てられた顧客の詳細が格納されている Customers テーブルのコピー、顧客に対応する窓口の詳細が格納された Contacts テーブルのコピーを提供するパブリケーションに対してサブスクライブします。たとえば、各営業担当者は、次のパブリケーションに対してサブスクライブします。
CREATE PUBLICATION SalesRepData ( TABLE SalesReps TABLE Customers SUBSCRIBE BY rep_key TABLE Contacts SUBSCRIBE BY (SELECT rep_key FROM Customers WHERE Contacts.cust_key = Customers.cust_key ) ); |
このパブリケーションの詳細については、切断データ分割の使用を参照してください。
サブスクライバ間のローの再割り当ては、営業担当者間に顧客を定期的に再割り当てする営業支援アプリケーションに共通の機能で、「領域の再編成」とも呼ばれます。
統合データベースでは、新しい営業担当者に顧客が再割り当てされると、Customers テーブルの rep_key 値が更新されます。
次の文では、顧客 cust1 を別の営業担当者 rep2 に再割り当てします。
UPDATE Customers SET rep_key = 'rep2' WHERE cust_key = 'cust1'; |
この更新は、次のようにレプリケートされます。
以前の営業担当者のリモート・データベースの Customers テーブルに対する DELETE 文として。
新しい営業担当者のリモート・データベースの Customers テーブルに対する INSERT 文として。
Contacts テーブルは変更されません。統合データベースのトランザクション・ログには、Contacts テーブルに関するエントリがありません。そのため、リモート・データベースの SQL Remote は、Contacts テーブルの cust_key ローを再割り当てできません。この再割り当てができないことによって、以前の営業担当者のリモート・データベースの Contacts テーブルには、すでに存在しない顧客の cust_key 値が含まれるという参照整合性の問題が発生します。
解決法としては、BEFORE UPDATE トリガを使用します。BEFORE UPDATE トリガはデータベース・テーブルをまったく変更しませんが、統合データベースのトランザクション・ログにエントリを作成します。
この BEFORE UPDATE トリガは、次のように起動する必要があります。
UPDATE 文が実行される前。したがって、ローの BEFORE 値が評価され、トランザクション・ログに追加されます。
各文ではなく FOR EACH ROW。トリガの提供する情報を新しいサブスクリプション式とする必要があります。
たとえば、次の文では、BEFORE UPDATE トリガを作成します。
CREATE TRIGGER "UpdateCustomer" BEFORE UPDATE OF "rep_key" // only fire the trigger when we modify rep_key, not any other column ORDER 1 ON "Cons"."Customers" /* REFERENCING OLD AS old_name NEW AS new_name */ REFERENCING NEW AS NewRow OLD AS OldRow FOR EACH ROW BEGIN // determine the new subscription expression // for the Customers table UPDATE Contacts PUBLICATION SalesRepData OLD SUBSCRIBE BY ( OldRow.rep_key ) NEW SUBSCRIBE BY ( NewRow.rep_key ) WHERE cust_key = NewRow.cust_key; END ; |
SQL Remote は、トランザクション・ログに記録された情報を使用して、どのサブスクライバがどのローを受信するかを決定します。
この文を実行した後、統合データベースのトランザクション・ログには 2 つのエントリが含まれています。
BEFORE UPDATE トリガによって生成された、Contacts テーブルの INSERT 文と DELETE 文。
--BEGIN TRIGGER-1029-0000461705 --BEGIN TRANSACTION-1029-0000461708 BEGIN TRANSACTION go --UPDATE PUBLICATION-1029-0000461711 Cons.Contacts --PUBLICATION-1029-0000461711-0002-NEW_SUBSCRIBE_BY-rep2 --PUBLICATION-1029-0000461711-0002-OLD_SUBSCRIBE_BY-rep1 --NEW-1029-0000461711 --INSERT INTO Cons.Contacts(contact_key,name,cust_key) --VALUES ('5','Joe','cust1') go --OLD-1029-0000461711 --DELETE FROM Cons.Contacts -- WHERE contact_key='5' go --END TRIGGER-1029-0000461743 |
実行された元の UPDATE 文と、それぞれローが挿入または削除されたユーザの INSERT 文と DELETE 文。
--PUBLICATION-1029-0000461746-0002-NEW_SUBSCRIBE_BY-rep2 --PUBLICATION-1029-0000461746-0002-OLD_SUBSCRIBE_BY-rep1 --NEW-1029-0000461746 --INSERT INTO Cons.Customers(cust_key,name,rep_key) --VALUES ('cust1','company1','rep2') go --OLD-1029-0000461746 --DELETE FROM Cons.Customers -- WHERE cust_key='cust1' go --UPDATE-1029-0000461746 UPDATE Cons.Customers SET rep_key='rep2' VERIFY (rep_key) VALUES ('1') WHERE cust_key='cust1' go --COMMIT-1029-0000461785 COMMIT WORK |
SQL Remote は、BEFORE タグと AFTER タグのトランザクション・ログをスキャンします。この情報に基づいて、どのリモート・ユーザが INSERT 文、UPDATE 文、または DELETE 文を取得するかが決定されます。
ユーザが BEFORE list に含まれていて AFTER list に含まれていない場合は、DELETE 文が Contacts テーブルに送信されます。
ユーザが AFTER list に含まれていて BEFORE list に含まれていない場合は、INSERT 文が Contacts テーブルに送信されます。
ユーザが BEFORE list と AFTER list の両方に含まれている場合は、Contacts テーブルに対して何も実行されませんが、Customers テーブルの UPDATE 文は送信されます。
BEFORE list と AFTER list の値が同じ場合は、リモート・ユーザがすでにローを保有しているため、UPDATE 文が送信されます。
次の例では、BEFORE UPDATE トリガを使用する必要があります。他のコンテキストでは、BEFORE DELETE トリガと BEFORE INSERT トリガが必要です。
UPDATE table-name PUBLICATION pub-name SUBSCRIBE BY sub-expression WHERE search-condition; |
この例では、BEFORE トリガを使用します。
UPDATE table-name PUBLICATION publication-name OLD SUBSCRIBE BY old-subscription-expression NEW SUBSCRIBE BY new-subscription-expression WHERE search-condition; |
UPDATE 文は、変更が適用されるパブリケーションとテーブルをリストします。文中の WHERE 句は、変更が適用されるローを示します。この UPDATE 文では、テーブルのデータは変更されませんが、トランザクション・ログにエントリが作成されます。
この例では、サブスクリプション式は 1 つの値を返します。ただし、複数の値を返すサブクエリも使用できます。サブスクリプション式の値は、更新を実行した後の値とする必要があります。
この例では、ローへのサブスクライバのみが新しい営業担当者になります。既存のサブスクライバと新しいサブスクライバを持つローの例については、重複分割の使用を参照してください。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |