Verwenden Sie die MERGE-Anweisung, um einen Aktualisierungsvorgang durchzuführen und große Mengen von Tabellendaten zu aktualisieren. Wenn Sie Daten zusammenführen, können Sie die Aktionen angeben, die durchgeführt werden sollen, wenn Zeilen aus den Quelldaten mit Zeilen in den Zieldaten übereinstimmen bzw. nicht übereinstimmen.
Das Folgende Syntax ist eine verkürzte Version der MERGE-Anweisung.
MERGE INTO target-object USING source-object ON merge-search-condition { WHEN MATCHED | WHEN NOT MATCHED } [...]
Wenn die Datenbank einen Zusammenführungsvorgang durchführt, vergleicht sie Zeilen im Quellobjekt (source-object) mit Zeilen im Zielobjekt (target-object), um Zeilen zu finden, die miteinander übereinstimmen bzw. nicht übereinstimmen, abhängig von der in der ON-Klausel enthaltenen Definition. Zeilen in source-object werden als übereinstimmend angesehen, wenn es zumindest eine Zeile in der Zieltabelle target-table gibt, sodass die Suchbedingung für die Zusammenführung (merge-search-condition) als TRUE ausgewertet wird.
Das Quellobjekt source-object kann eine Basistabelle, eine Ansicht, eine materialisierte Ansicht, eine abgeleitete Tabelle oder die Ergebnisse einer Prozedur sein. Das Zielobjekt target-object kann jedes dieser Objekte außer einer materialisierten Ansichten und Prozeduren sein.
Der ANSI SQL/2008-Standard lässt nicht zu, dass während eines Zusammenführungsvorgangs Zeilen im target-object mit mehr als einer Zeile im source-object aktualisiert werden.
Wenn eine Zeile im source-object als übereinstimmend oder nicht-übereinstimmend angesehen wird, wird sie anhand der übereinstimmenden bzw. nicht-übereinstimmenden WHEN-Klauseln (WHEN MATCHED oder WHEN NOT MATCHED) evaluiert. Eine WHEN MATCHED-Klausel legt die Aktion fest, die auf der Zeile im target-object durchgeführt wird (WHEN MATCHED ... UPDATE beispielsweise gibt eine Aktualisierung der Zeile im target-object an). Eine WHEN NOT MATCHED-Klausel definiert eine Aktion, die auf dem target-object unter Verwendung von nicht übereinstimmenden Zeilen des source-object durchzuführen ist.
Sie können beliebig viele WHEN-Klauseln angeben, die in der von Ihnen angegebenen Reihenfolge abgearbeitet werden. Sie können auch die AND-Klausel innerhalb der WHEN-Klausel verwenden, um Aktionen für eine Teilmenge der Zeilen anzugeben. Beispiel: Die folgenden WHEN-Klauseln legen verschiedene auszuführende Aktionen fest, abhängig vom Wert der Quantity-Spalte bei übereinstimmenden Zeilen:
WHEN MATCHED AND myTargetTable.Quantity<=500 THEN SKIP WHEN MATCHED AND myTargetTable.Quantity>500 THEN UPDATE SET myTargetTable.Quantity=500 |
Das Gruppieren von übereinstimmenden und nicht-übereinstimmenden Zeilen wird als Verzweigung bezeichnet, und die einzelnen Gruppen werden Zweige genannt. Eine Verzweigung entspricht einer einzelnen WHEN MATCHED- oder WHEN NOT MATCHED-Klausel. Beispiel: Ein Zweig enthält die Menge von nicht-übereinstimmenden Zeilen aus dem source-object, die eingefügt werden muss. Die Ausführung der Zweigaktionen beginnt erst, nachdem alle Verzweigungsaktionen abgeschlossen wurden (alle Zeilen im source-object wurden ausgewertet). Der Datenbankserver beginnt mit der Ausführung der Zweigaktionen entsprechend der Reihenfolge, in der die WHEN-Klauseln angegeben wurden.
Wenn eine nicht übereinstimmende Zeile aus dem source-object oder ein Paar übereinstimmender Zeilen aus dem source-object und dem target-object in eine Verzweigung gesetzt werden, erfolgt keine weitere Auswertung gegenüber nachfolgenden Verzweigungen. Dadurch ist die Reihenfolge, in der Sie WHEN-Klauseln angeben, entscheidend.
Eine Zeile im source-object, die als Übereinstimmung oder Nicht-Übereinstimmung angesehen wird, die aber zu keiner Verzweigung gehört (d.h. sie erfüllt keine der WHEN-Klauseln), wird ignoriert. Das kann eintreten, wenn die WHEN-Klauseln AND-Klauseln enthalten und die Zeile keine der AND-Klauselbedingungen erfüllt. In diesem Fall wird die Zeile ignoriert, da für sie keine Aktion festgelegt ist.
Im Transaktionslog werden Aktionen, die Daten ändern, als einzelne INSERT-, UPDATE- und DELETE-Anweisungen protokolliert.
Trigger werden üblicherweise ausgelöst, wenn die einzelnen INSERT-, UPDATE- und DELETE-Anweisungen während des Zusammenführungsvorgangs ausgeführt werden. Beispiel: Bei der Prozessverarbeitung eines Zweigs, für den eine UPDATE-Aktion festgelegt ist, führt der Datenbankserver Folgendes durch:
Er löst alle BEFORE UPDATE-Trigger aus.
Er führt die UPDATE-Anweisung auf der Kandidatenmenge von Zeilen durch, während er etwaige UPDATE-Trigger auf Zeilenebene auslöst.
Er löst die AFTER UPDATE-Trigger aus.
Trigger für die Zieltabelle target-table können während eines Zusammenführungsvorgangs Konflikte bewirken, wenn dieser sich auf Zeilen auswirkt, die für eine andere Verzweigung aktualisiert werden. Beispiel: Angenommen, eine Aktion wird in der Zeile A ausgeführt, wonach ein Trigger auslöst, der die Zeile B löscht. Für B ist allerdings eine Aktion definiiert, die noch nicht durchgeführt wurde. Wenn eine Aktion nicht auf einer Zeile durchgeführt werden kann, schlägt der Zusammenführungsvorgang fehl, alle Änderungen werden zurückgesetzt und ein Fehler wird gemeldet.
Ein Trigger, für den mehr als eine Trigger-Aktion festgelegt ist, wird behandelt, als ob er einmal für jede der Trigger-Aktionen im selben Hauptteil angegeben wurde (was äquivalent mit der Definition von separaten Trigger, jeweils mit einer einzelnen Trigger-Aktion, ist).
Die Performance des Datenbankservers kann beeinträchtigt werden, wenn die MERGE-Anweisung eine große Anzahl von Zeilen aktualisiert. Um zahlreiche Zeilen zu aktualisieren, sollten Sie in Betracht ziehen, die Daten in abhängigen sofortigen materialisierten Ansichten zu kürzen, bevor Sie die MERGE-Anweisung für die Tabelle ausführen. Nachdem Sie die MERGE-Anweisung ausgeführt haben, führen Sie eine REFRESH MATERIALIZED VIEW-Anweisung aus.
Die Performance des Datenbankservers kann beeinträchtigt werden, wenn die MERGE-Anweisung eine große Anzahl von Zeilen aktualisiert. Ziehen Sie daher in Betracht, Textindizes zu löschen, bevor Sie die MERGE-Anweisung für eine Tabelle ausführen. Nachdem Sie die MERGE-Anweisung ausgeführt haben, erstellen Sie den Textindex neu.
Angenommen, Sie haben ein kleines Unternehmen, das Jacken und Pullover vertreibt. Die Preise der Stoffe für die Jacken sind um 5% gestiegen, und Sie wollen Ihre Preise entsprechend anpassen. Unter Verwendung der folgenden CREATE TABLE-Anweisung erstellen Sie eine kleine Tabelle namens "myProducts", um aktuelle Preisinformationen für die von Ihnen verkauften Jacken und Pullover aufzunehmen. Die nachfolgenden INSERT-Anweisungen füllen "myProducts" mit Daten an. Für dieses Beispiel müssen Sie das CREATE TABLE-Privileg haben.
CREATE TABLE myProducts ( product_id NUMERIC(10), product_name CHAR(20), product_size CHAR(20), product_price NUMERIC(14,2)); INSERT INTO myProducts VALUES (1, 'Jacket', 'Small', 29.99); INSERT INTO myProducts VALUES (2, 'Jacket', 'Medium', 29.99); INSERT INTO myProducts VALUES (3, 'Jacket', 'Large', 39.99); INSERT INTO myProducts VALUES (4, 'Sweater', 'Small', 18.99); INSERT INTO myProducts VALUES (5, 'Sweater', 'Medium', 18.99); INSERT INTO myProducts VALUES (6, 'Sweater', 'Large', 19.99); SELECT * FROM myProducts; |
product_id | product_name | product_size | product_price |
---|---|---|---|
1 | Jacket | Small | 29.99 |
2 | Jacket | Medium | 29.99 |
3 | Jacket | Large | 39.99 |
4 | Sweater | Small | 18.99 |
5 | Sweater | Medium | 18.99 |
6 | Sweater | Large | 19.99 |
Nun verwenden Sie die folgende Anweisung, um die Tabelle "myPrice" zu erstellen, um Informationen über die Preisänderungen bei Jacken aufzunehmen. Eine SELECT-Anweisung wird am Ende hinzugefügt, damit Sie den Inhalt der myPrice-Tabelle sehen können, bevor der Zusammenführungsvorgang durchgeführt wird.
CREATE TABLE myPrices ( product_id NUMERIC(10), product_name CHAR(20), product_size CHAR(20), product_price NUMERIC(14,2), new_price NUMERIC(14,2)); INSERT INTO myPrices (product_id) VALUES (1); INSERT INTO myPrices (product_id) VALUES (2); INSERT INTO myPrices (product_id) VALUES (3); INSERT INTO myPrices (product_id) VALUES (4); INSERT INTO myPrices (product_id) VALUES (5); INSERT INTO myPrices (product_id) VALUES (6); SELECT * FROM myPrices; |
product_id | product_name | product_size | product_price | new_price |
---|---|---|---|---|
1 | (NULL) | (NULL) | (NULL) | (NULL) |
2 | (NULL) | (NULL) | (NULL) | (NULL) |
3 | (NULL) | (NULL) | (NULL) | (NULL) |
4 | (NULL) | (NULL) | (NULL) | (NULL) |
5 | (NULL) | (NULL) | (NULL) | (NULL) |
6 | (NULL) | (NULL) | (NULL) | (NULL) |
Verwenden Sie die folgende MERGE-Anweisung, um Daten aus der myProducts-Tabelle in der myPrices-Tabelle zusammenzuführen. Beachten Sie, dass das source-object eine abgeleitete Tabelle ist, die gefiltert wurde, um nur jene Zeilen zu enthalten, bei denen product_name "Jacket" ist. Beachten Sie außerdem, dass die ON-Klausel angibt, dass Zeilen im target-object und im source-object übereinstimmen, wenn die Werte in ihren product_id-Spalten übereinstimmen.
MERGE INTO myPrices p USING ( SELECT product_id, product_name, product_size, product_price FROM myProducts WHERE product_name='Jacket') pp ON (p.product_id = pp.product_id) WHEN MATCHED THEN UPDATE SET p.product_id=pp.product_id, p.product_name=pp.product_name, p.product_size=pp.product_size, p.product_price=pp.product_price, p.new_price=pp.product_price * 1.05; SELECT * FROM myPrices; |
product_id | product_name | product_size | product_price | new_price |
---|---|---|---|---|
1 | Jacket | Small | 29.99 | 31.49 |
2 | Jacket | Medium | 29.99 | 31.49 |
3 | Jacket | Large | 39.99 | 41.99 |
4 | (NULL) | (NULL) | (NULL) | (NULL) |
5 | (NULL) | (NULL) | (NULL) | (NULL) |
6 | (NULL) | (NULL) | (NULL) | (NULL) |
Die Spaltenwerte für product_id 4, 5 und 6 bleiben NULL, weil diese Produkte nicht zu einer der Zeilen in der Tabelle myProducts
passen, deren Produkte (product_name='Jacket'
) waren.
Im folgenden Beispiel werden Zeilen von den Tabellen mySourceTable und myTargetTable mithilfe der Primärschlüsselwerte von myTargetTable zur Suche nach übereinstimmenden Zeilen zusammengeführt. Die Zeile wird als übereinstimmend angesehen, wenn eine Zeile in mySourceTable denselben Wert wie die Primärschlüsselspalte von myTargetTable hat.
MERGE INTO myTargetTable USING mySourceTable ON PRIMARY KEY WHEN NOT MATCHED THEN INSERT WHEN MATCHED THEN UPDATE; |
Die WHEN NOT MATCHED THEN INSERT-Klausel gibt an, dass Zeilen, die in mySourceTable gefunden werden und in myTargetTable nicht zu finden sind, der myTargetTable hinzugefügt werden müssen. Die WHEN MATCHED THEN UPDATE-Klausel gibt an, dass übereinstimmende Zeilen von myTargetTable mit den Werten in mySourceTable aktualisiert werden.
Die nachstehende Syntax ist der obenstehenden Syntax gleichwertig. Sie setzt voraus, dass myTargetTable die Spalten (I1, I2, .. In) hat und der Primärschlüssel für die Spalten (I1, I2) definiert ist. Die mySourceTable hat die Spalten (U1, U2, .. Un).
MERGE INTO myTargetTable ( I1, I2, .. ., In ) USING mySourceTable ON myTargetTable.I1 = mySourceTable.U1 AND myTargetTable.I2 = mySourceTable.U2 WHEN NOT MATCHED THEN INSERT ( I1, I2, .. In ) VALUES ( mySourceTable.U1, mySourceTable.U2, ..., mySourceTable.Un ) WHEN MATCHED THEN UPDATE SET myTargetTable.I1 = mySourceTable.U1, myTargetTable.I2 = mySourceTable.U2, ... myTargetTable.In = mySourceTable.Un; |
Eine der Aktionen, die Sie für eine Übereinstimmungs- oder Nicht-Übereinstimmungsaktion angeben können, ist RAISERROR. RAISERROR ermöglicht es Ihnen, den Zusammenführungsvorgang fehlschlagen zu lassen, wenn die Bedingung einer WHEN-Klausel erfüllt wird.
Wenn Sie RAISERROR angeben, gibt der Datenbankserver standardmäßig SQLSTATE 23510 und SQLCODE -1254 zurück. Optional können Sie den zurückgegebenen SQLCODE anpassen, indem Sie den error_number-Parameter nach dem RAISERROR-Schlüsselwort angeben.
Die Angabe eines benutzerdefinierten SQLCODE ist sinnvoll, wenn Sie später versuchen, die spezifischen Umstände zu ermitteln, die zu dem Fehler geführt haben.
Der benutzerdefinierte SQLCODE muss eine positive Ganzzahl größer als 17.000 sein und kann entweder als Zahl oder als Variable angegeben werden.
Die folgenden Anweisungen zeigen auf einfache Weise, wie sich das Anpassen eines benutzerdefinierten SQLCODE auf die Rückgabe auswirkt. Für dieses Beispiel müssen Sie das CREATE TABLE-Privileg haben.
Erstellen Sie folgendermaßen die Tabelle "targetTable":
CREATE TABLE targetTable( c1 int ); INSERT INTO targetTable VALUES( 1 ); |
Die folgende Anweisung gibt einen Fehler mit SQLSTATE = '23510' und SQLCODE = -1254 zurück:
MERGE INTO targetTable USING (SELECT 1 c1 ) AS sourceData ON targetTable.c1 = sourceData.c1 WHEN MATCHED THEN RAISERROR; SELECT sqlstate, sqlcode; |
Die folgende Anweisung gibt einen Fehler mit SQLSTATE = '23510' und SQLCODE = -17001 zurück:
MERGE INTO targetTable USING (SELECT 1 c1 ) AS sourceData ON targetTable.c1 = sourceData.c1 WHEN MATCHED THEN RAISERROR 17001 WHEN NOT MATCHED THEN RAISERROR 17002; SELECT sqlstate, sqlcode; |
Die folgende Anweisung gibt einen Fehler mit SQLSTATE = '23510' und SQLCODE = -17002 zurück:
MERGE INTO targetTable USING (SELECT 2 c1 ) AS sourceData ON targetTable.c1 = sourceData.c1 WHEN MATCHED THEN RAISERROR 17001 WHEN NOT MATCHED THEN RAISERROR 17002; SELECT sqlstate, sqlcode; |
![]() |
Kommentieren Sie diese Seite in DocCommentXchange.
|
Copyright © 2013, SAP AG oder ein SAP-Konzernunternehmen. - SAP Sybase SQL Anywhere 16.0 |