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 Anywhere Server - SQL-Benutzerhandbuch » Ferndatenzugriff und Arbeit mit Massendaten » Daten importieren und exportieren » Daten importieren

 

Daten mit der MERGE-Anweisung importieren

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.

Zusammenführungsverhalten definieren

Das Folgende ist eine verkürzte Version der MERGE-Anweisungssyntax zur Erläuterung. Die vollständige Syntax der MERGE-Anweisung finden Sie unter MERGE-Anweisung.

MERGE INTO Zielobjekt
USING Quellobjekt
ON Zusammenführungs_Suchbedingung
{ WHEN MATCHED | WHEN NOT MATCHED } [...]

Wenn die Datenbank einen Zusammenführungsvorgang durchführt, vergleicht sie Zeilen im Quellobjekt mit Zeilen im Zielobjekt, um Zeilen zu finden, die miteinander übereinstimmen bzw. nicht übereinstimmen, abhängig von der in der ON-Klausel enthaltenen Definition. Zeilen im Quellobjekt werden als übereinstimmend angesehen, wenn es zumindest eine Zeile in der Zieltabelle gibt, sodass die Zusammenführungs-Suchbedingung als TRUE ausgewertet wird.

Das Quellobjekt kann eine Basistabelle, eine Ansicht, eine materialisierte Ansicht, eine abgeleitete Tabelle oder die Ergebnisse einer Prozedur sein. Das Zielobjekt kann jedes dieser Objekte außer einer materialisierten Ansichten und Prozeduren sein. Weitere Einschränkungen für diese Objekttypen finden Sie unter MERGE-Anweisung.

Der ANSI SQL/2003-Standard lässt nicht zu, dass während eines Zusammenführungsvorgangs Zeilen im Zielobjekt mit mehr als einer Zeile im Quellobjekt aktualisiert werden.

Wenn eine Zeile im Quellobjekt 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 Zielobjekt durchgeführt wird (WHEN MATCHED ... UPDATE beispielsweise gibt eine Aktualisierung der Zeile im Zielobjekt an). Eine WHEN NOT MATCHED-Klausel definiert eine Aktion, die auf dem Zielobjekt unter Verwendung von nicht übereinstimmenden Zeilen des Quellobjekts 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
Verzweigungen in einem Zusammenführungsvorgang

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 Quellobjekt, die eingefügt werden muss. Die Ausführung der Zweigaktionen beginnt erst, nachdem alle Verzweigungsaktionen abgeschlossen wurden (alle Zeilen im Quellobjekt 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 Quellobjekt oder ein Paar übereinstimmender Zeilen aus dem Quellobjekt und dem Zielobjekt 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 Quellobjekt, 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.

Für die Zieltabelle definierte Trigger

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:

  1. Er löst alle BEFORE UPDATE-Trigger aus.

  2. Er führt die UPDATE-Anweisung auf der Kandidatenmenge von Zeilen durch, während er etwaige UPDATE-Trigger auf Zeilenebene auslöst.

  3. Er löst die AFTER UPDATE-Trigger aus.

Trigger der Zieltabelle 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).

Überlegungen zu sofortigen materialisierten Ansichten

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. Weitere Hinweise finden Sie unter REFRESH MATERIALIZED VIEW-Anweisung und TRUNCATE-Anweisung.

Überlegungen zu Textindizes

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. Weitere Hinweise finden Sie unter DROP TEXT INDEX-Anweisung und CREATE TEXT INDEX-Anweisung.

Beispiel 1

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.

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);
COMMIT;
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 Quellobjekt 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 Zielobjekt und im Quellobjekt ü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.

Beispiel 2

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;
Die RAISERROR-Aktion verwenden

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. Weitere Hinweise finden Sie unter MERGE-Anweisung.

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:

Erstellen Sie folgendermaßen die Tabelle "targetTable":

CREATE TABLE targetTable( c1 int );
INSERT INTO targetTable VALUES( 1 );
COMMIT;

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;