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

SQL Anywhere 11.0.1 (Deutsch) » SQL Remote » SQL Remote-Replikationsplanung » SQL Remote-Replikation planen und einrichten » Disjunkte Datenpartitionen verwenden

 

BEFORE UPDATE-Trigger verwenden

Im folgenden Beispiel speichern drei Tabellen Informationen über die Interaktionen zwischen Handelsvertretern und Kunden: Customers, Contacts und SalesReps. Jeder Handelsvertreter bedient mehrere Kunden. Bei manchen Kunden gibt es einen einzigen Kontakt, während andere Kunden mehrere Kontakte haben.

Die Contacts-Tabelle hat einen Fremdschlüssel zur Customers-Tabelle. Die Customers-Tabelle hat einen Fremdschlüssel zur SalesReps-Tabelle.

Eine detaillierte Beschreibung der Tabellen finden Sie unter Beschreibung der Contacts-, Customers- und SalesReps-Tabellen.

Ein Handelsvertreter subskribiert eine Publikation, die eine Kopie der SalesRep-Tabelle, eine Kopie der Customers-Tabelle mit den ihm zugeordneten Kunden und eine Kopie der Contacts-Tabelle mit den Details der Kontakte bereitstellt, die sich auf seine Kunden beziehen. Beispiel: Jeder Handelsvertreter subskribiert die folgende Publikation:

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 )
);

Eine detaillierte Beschreibung dieser Publikation finden Sie unter Disjunkte Datenpartitionen verwenden.

Referenzielle Integrität bewahren

Diese Neuzuweisung von Zeilen wird manchmal als territoriale Neuaufteilung bezeichnet, da sie eine übliche Eigenschaft bei Anwendungen ist, die den Verkauf automatisieren und bei denen Kunden dem Verkaufspersonal regelmäßig neu zugeordnet werden.

Wenn ein Kunde einem neuen Handelsvertreter zugewiesen wird, erfolgt in der konsolidierten Datenbank eine Aktualisierung des rep_key-Werts in der Customers-Tabelle.

Die folgende Anweisung weist einem Kunden, cust1, einen anderen Handelsvertreter, rep2, zu..

UPDATE Customers
SET rep_key = 'rep2'
WHERE cust_key = 'cust1';

Diese Aktualisierung wird folgendermaßen repliziert:

  • Als DELETE-Anweisung in der Customers-Tabelle in der entfernten Datenbank des alten Handelsvertreters.

  • Als INSERT-Anweisung in der Customers-Tabelle in der entfernten Datenbank des neuen Handelsvertreters.

Die Contacts-Tabelle wird nicht geändert. Es gibt keine Einträge im Transaktionslog der konsolidierten Datenbank zur Contacts-Tabelle. Das führt dazu, dass SQL Remote in den entfernten Datenbanken nicht in der Lage ist, die cust_key-Zeilen der Contacts-Tabelle neu zuzuweisen. Das kann das folgende Problem mit der referenziellen Integrität bewirken: Die Contacts-Tabelle in der entfernten Datenbank des alten Handelsvertreters enthält einen cust_key-Wert, für den es keine Kunden in der Tabelle mehr gibt.

Eine Lösung ist die Verwendung eines BEFORE UPDATE-Triggers. Ein BEFORE UPDATE-Trigger führt keine Änderungen in den Datenbanktabellen durch, aber erstellt einen Eintrag im Transaktionslog der konsolidierten Datenbank.

Dieser BEFORE UPDATE-Trigger muss folgendermaßen ausgelöst werden:

  • Bevor die UPDATE-Anweisung ausgeführt wird, damit der BEFORE-Wert der Zeile ausgewertet und dem Transaktionslog hinzugefügt wird.

  • FOR EACH ROW anstatt für jede Anweisung. Die vom Trigger gelieferten Informationen müssen der neue Subskriptionsausdruck sein.

Beispiel: Die folgende Anweisung erstellt einen BEFORE UPDATE-Trigger.

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 verwendet die im Transaktionslog aufgezeichneten Informationen, um zu ermitteln, welche Subskribenten welche Zeilen erhalten.

Das Transaktionslog der konsolidierten Datenbank enthält zwei Einträge, nachdem diese Anweisung ausgeführt wurde:

  • INSERT- und DELETE-Anweisungen für die Contacts-Tabelle, die vom BEFORE UPDATE-Trigger generiert wurden.

    --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
    
  • Die ursprüngliche UPDATE-Anweisung, die ausgeführt wurde, sowie INSERT- und DELETE-Anweisungen für jene Benutzer, die eine Zeile gewonnen bzw. verloren haben.

    --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 durchsucht das Transaktionslog nach den BEFORE- und AFTER-Parametern. Basierend auf diesen Informationen kann ermittelt werden, welche entfernten Benutzer eine INSERT-, UPDATE- oder DELETE-Anweisung erhalten.

  • Wenn ein Benutzer in der BEFORE-Liste und nicht in der AFTER-Liste steht, wird eine DELETE-Anweisung in der Contacts-Tabelle gesendet.

  • Wenn ein Benutzer in der AFTER-Liste und nicht in der BEFORE-Liste steht, wird eine INSERT-Anweisung in der Contacts-Tabelle gesendet.

  • Wenn ein Benutzer sowohl in der BEFORE- als auch der AFTER-Liste steht, wird nichts in der Contacts-Tabelle durchgeführt, aber die UPDATE-Anweisung in der Customers-Tabelle wird gesendet.

Wenn die BEFORE- und AFTER-Listen identisch sind, besitzt der entfernte Benutzer die Zeile bereits und es wird eine UPDATE-Anweisung gesendet.

Hinweise zu Triggern

Im folgenden Beispiel müssen Sie einen BEFORE UPDATE-Trigger verwenden. In anderen Fällen sind BEFORE DELETE und BEFORE INSERT erforderlich.

UPDATE Tabellenname
PUBLICATION Publikationsname
   SUBSCRIBE BY Unterausdruck
WHERE Suchbedingung;

In diesem Beispiel verwenden Sie einen BEFORE-Trigger.

UPDATE Tabellenname 
PUBLICATION  Publikationsname 
   OLD SUBSCRIBE BY   alter_Subskriptionsausdruck 
   NEW SUBSCRIBE BY    neuer_Subskriptionsausdruck 
WHERE  Suchbedingung;

Die UPDATE-Anweisung listet die betroffene Publikation und Tabelle auf. Die WHERE-Klausel in der Anweisung beschreibt die betroffenen Zeilen. Die UPDATE-Anweisung ändert nicht die Daten in der Tabelle; sie führt Einträge im Transaktionslog durch.

In diesem Beispiel gibt der Subskriptionsausdruck einen einzelnen Wert zurück. Unterabfragen, die mehrere Werte ausgeben, können allerdings ebenfalls verwendet werden. Der Wert des Subskriptionsausdrucks muss der Wert nach der Aktualisierung sein.

In diesem Beispiel ist der einzige Subskribent der Zeile der neue Handelsvertreter. Ein Beispiel für eine Zeile, die bestehende und neue Subskribenten hat, finden Sie unter Überlappungspartitionen verwenden.