Question

Je l'ai déclaré le tableau suivant pour une utilisation par les déclencheurs d'audit:

CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
  1. Le déclencheur s'invoqué à plusieurs reprises dans la même transaction.

  2. La première fois que le déclencheur est appelé, je le veux pour insérer une nouvelle ligne avec la TRANSACTION_ID de courant () et le temps.

  3. Les temps suivants, le déclencheur est appelé, je veux qu'il revienne l'actuel « id » (je invoque Statement.getGeneratedKeys () à cette fin) sans altérer "UUID" ou "temps".

Le schéma actuel semble avoir deux problèmes.

  1. Quand je Invoke MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW()) que je reçois: 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. Je soupçonne que l'invocation MERGE sur une ligne existante va modifier le "temps".

Comment puis-je résoudre ces deux problèmes?

Était-ce utile?

La solution

MERGE est analogue à java.util.Map.put(key, value): il insère la ligne si elle n'existe pas, et mettre à jour la ligne si elle le fait. Cela étant dit, vous pouvez toujours se fondre dans une table contenant des colonnes AUTO_INCREMENT tant que vous utilisez une autre colonne comme la clé.

Étant donné customer[id identity, email varchar(30), count int] vous pouvez 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). Signification, réutilisent l'id si un enregistrement existe, null CONTRAIRE.

Voir aussi https://stackoverflow.com/a/18819879/14731 un moyen portable pour insérer ou -update selon si une ligne existe déjà.


1. (EN audit_transaction_ids MERGE UUID, temps) KEY (id) VALUES (TRANSACTION_ID (), NOW ())

Si vous voulez juste insérer une nouvelle ligne, utilisez: INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())

MERGE sans réglage de la valeur pour la ID colonne n'a pas de sens si ID est utilisé comme la clé, car de cette manière, il ne pourrait jamais (même en théorie) mettre à jour une des lignes existantes. Ce que vous pouvez faire est en utilisant une autre colonne de clé (dans le cas ci-dessus il n'y a pas de colonne qui pourrait être utilisé). Consultez la documentation de MERGE pour plus de détails.

2. MERGE sur une invocation de ligne existante modifiera le "temps"

Je ne sais pas si vous parlez du fait que la valeur de la colonne « temps » est modifiée. Ceci est le comportement attendu si vous utilisez MERGE ... VALUES(.., NOW()), car l'instruction MERGE est censé mettre à jour cette colonne.

Ou peut-être vous dire que les anciennes versions de H2 sont revenus des valeurs différentes dans la même transaction (contrairement à la plupart des autres bases de données, qui renvoient la même valeur dans la même transaction). Cela est vrai, mais avec la version H2 1.3.155 (2011-05-27) et plus tard, cette incompatibilité est fixée. Voir aussi la changement journal : « CURRENT_TIMESTAMP () et ainsi de suite retourner maintenant la même valeur dans une transaction « . On dirait que ce n'est pas le problème dans votre cas, parce que vous ne semblez utiliser la version 1.3.155 (le message d'erreur [90081-155] comprend le numéro de version / build).

Autres conseils

Short Answer:

MERGE INTO AUDIT_TRANSACTION_IDS (uuid, time) KEY (uuid, time) VALUES (TRANSACTION_ID(), NOW());

little performance tip: make sure uuid is indexed

Long Answer:

MERGE is basically an UPDATE which INSERTs when no record found to be updated.

Wikipedia gives a more concise, standardized syntax of MERGE but you have to supply your own update and insert. (Whether this will be supported in H2 or not is not mine to answer)

So how do you update a record using MERGE in H2? You define a key to be looked up for, if it is found you update the row (with column names you supply, and you can define DEFAULT here, to reset your columns to its defaults), otherwise you insert the row.

Now what is Null? Null means unknown, not found, undefined, anything which is not what you're looking for.

That is why Null works as key to be looked up for. Because it means the record is not found.

MERGE INTO table1 (id, col1, col2) KEY(id) VALUES (Null, 1, 2)

Null has a value. it IS a value.

Now let's see your SQL.

MERGE INTO table1 (id, col1, col2) KEY(id) VALUES (DEFAULT, 1, 2)

What is that implying? To me, it says I have this [DEFAULT, 1, 2], find me a DEFAULT in column id, then update col1 to 1, col2 to 2, if found. otherwise, insert default to id, 1 to col1, 2 to col2.

See what I emphasized there? What does that even mean? What is DEFAULT? How do you compare DEFAULT to id?

DEFAULT is just a keyword.

You can do stuff like,

MERGE INTO table1 (id, col1, timeStampCol) KEY(id) VALUES (Null, 1, DEFAULT)

but don't put DEFAULT in the key column.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top