Frage

Ich habe die folgende Tabelle für die Verwendung durch Audit -Trigger deklariert:

CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
  1. Der Auslöser wird in derselben Transaktion mehrfach aufgerufen.

  2. Wenn der Trigger zum ersten Mal aufgerufen wird, möchte ich, dass er eine neue Zeile mit dem aktuellen Transaction_id () und der Zeit einfügt.

  3. In den folgenden Zeiten, in denen der Auslöser aufgerufen wird, möchte ich, dass er die vorhandene "ID" (ich habe Anweisung aufgerufen.

Das aktuelle Schema scheint zwei Probleme zu haben.

  1. Wenn ich aufrufe MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW()) Ich bekomme: org.h2.jdbc.JdbcSQLException: Column "ID" contains null values; SQL statement: MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES (TRANSACTION_ID(), NOW()) [90081-155]

  2. Ich vermute, dass das Aufrufen von Zusammenführungen in einer vorhandenen Reihe "Zeit" verändert wird.

Wie behebe ich beide Probleme?

War es hilfreich?

Lösung

MERGE ist analog zu java.util.Map.put(key, value): Es wird die Zeile eingefügt, wenn sie nicht vorhanden ist, und aktualisieren die Zeile, wenn dies der Fall ist. Davon abgesehen können Sie sich immer noch in einen Tisch verschmelzen, der enthält AUTO_INCREMENT Spalten, solange Sie eine andere Spalte als Schlüssel verwenden.

Gegeben customer[id identity, email varchar(30), count int] Sie könnten merge into customer(id, email, count) key(email) values((select max(id) from customer c2 where c2.email='test@acme.com'), 'test@acme.com', 10). Dennoch verwenden Sie die ID erneut, wenn ein Datensatz vorhanden ist, und verwenden Sie sonst NULL.

Siehe auch https://stackoverflow.com/a/18819879/14731 Für eine tragbare Möglichkeit zum Einfügen oder Update, je nachdem, ob bereits eine Reihe vorhanden ist.


1. Führen Sie in Audit_transaction_ids (UUID, Zeit) Key (ID) -Werte (transaction_id (), now ()) zusammen

Wenn Sie nur eine neue Zeile einfügen möchten, verwenden Sie:INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())

MERGE ohne den Wert für die Spalte festzulegen ID macht keinen Sinn, wenn ID wird als Schlüssel verwendet, da es auf diese Weise (sogar theoretisch) eine vorhandene Zeilen niemals aktualisieren könnte. Sie können eine andere Schlüsselspalte verwenden (im obigen Fall gibt es keine Spalte, die verwendet werden könnte). Siehe die Dokumentation für MERGE für Details.

2. Das Aufrufen von Merge in einer vorhandenen Zeile wird die "Zeit" verändern

Ich bin mir nicht sicher, ob Sie über die Tatsache sprechen, dass der Wert der Spalte "Zeit" geändert wird. Dies ist das erwartete Verhalten, wenn Sie verwenden MERGE ... VALUES(.., NOW()), weil die MERGE Die Anweisung soll diese Spalte aktualisieren.

Oder vielleicht meinen Sie, dass ältere Versionen von H2 in derselben Transaktion unterschiedliche Werte zurückgegeben haben (im Gegensatz zu den meisten anderen Datenbanken, die denselben Wert innerhalb derselben Transaktion zurückgeben). Dies gilt jedoch mit H2 Version 1.3.155 (2011-05-27) und später ist diese Inkompatibilität festgelegt. Siehe auch die Änderungsprotokoll: "Current_timestamp () und so weiter geben Sie jetzt den gleichen Wert innerhalb einer Transaktion zurück." Es sieht so aus, als wäre dies nicht das Problem in Ihrem Fall, da Sie Version 1.3.155 zu verwenden scheinen (die Fehlermeldung [90081-155] enthält die Build- / Versionsnummer).

Andere Tipps

Kurze Antwort:

Führen Sie in Audit_Transaction_ids (UUID, Zeit) Key (UUID, Zeit) Werte (transaction_id (), Now ());

Little Performance Tipp: Stellen Sie sicher, dass UUID indiziert ist

Lange Antwort:

MERGE ist im Grunde ein UPDATE die INSERTs Wenn kein Datensatz aktualisiert wurde.

Wikipedia gibt eine prägnantere, standardisierte Syntax vonVERSCHMELZEN Sie müssen jedoch Ihr eigenes Update und einfügen. (Ob dies in H2 unterstützt wird oder nicht, ist nicht meine, um zu antworten)

Wie aktualisiert man einen Datensatz mithilfe? MERGE in H2? Sie definieren einen Schlüssel, nach dem Sie nachsehen können. Wenn Sie festgestellt werden, dass Sie die Zeile aktualisieren (mit den Spaltennamen, die Sie angeben, können Sie definieren DEFAULT Hier setzen Sie die Zeile ein, um Ihre Spalten auf die Standardeinstellungen zurückzusetzen.

Was ist nun? Null? Null bedeutet unbekannt, nicht gefunden, undefiniert, alles, was nicht das ist, wonach Sie suchen.

Deswegen Null Funktioniert als Schlüssel, um nachzuschauen. Weil es bedeutet, dass der Datensatz nicht gefunden wird.

Zusammenführen in Tabelle 1 (ID, Col1, Col2) Key (ID) -Werte (Null, 1, 2)

Null hat einen Wert. Es ist ein Wert.

Jetzt sehen wir Ihre SQL.

Zusammenführen in Tabelle 1 (ID, Col1, Col2) Key (ID) -Werte (Standard, 1, 2)

Was bedeutet das? Für mich heißt es, ich habe diesen [Standard, 1, 2], finde mich a DEFAULT in der Spalte id, dann aktualisieren col1 bis 1, col2 bis 2, falls gefunden. Andernfalls fügen Sie Standard einfügen zu id, 1 zu col1, 2 bis col2.

Sehen Sie, was ich dort betont habe? Was bedeutet das überhaupt? Was ist DEFAULT? Wie vergleichen Sie DEFAULT zu id?

DEFAULT ist nur ein Schlüsselwort.

Sie können Dinge wie, wie

Zusammenführen in Tabelle 1 (ID, Col1, Timestampcol) Key (ID) -Werte (Null, 1, Standard)

Stecken Sie jedoch nicht Standard in der Schlüsselspalte.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top