UNIRE IN tabella contenente colonne AUTO_INCREMENT
Domanda
Ho dichiarato la seguente tabella per l'utilizzo da parte di trigger di controllo:
CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
Il trigger viene richiamato più volte nella stessa transazione.
La prima volta che il grilletto è richiamato, voglio inserire un nuovo riga con l'attuale TRANSACTION_ID() e tempo.
Le volte successive il trigger viene richiamato, voglio tornare l'esistente "id" (invoco Istruzione.getGeneratedKeys() alla fine) senza alterare "uuid" o "tempo".
L'attuale schema sembra avere due problemi.
Quando invoco
MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW())
Ottengo: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]
Ho il sospetto che la chiamata di UNIRE su una riga esistente alterare "il tempo".
Come faccio a risolvere entrambi questi problemi?
Soluzione
MERGE
analoga è la java.util.Map.put(key, value)
:si inserisce la riga, se non esiste, e l'aggiornamento della riga, se lo fa.Detto questo, è ancora possibile unire in una tabella contenente AUTO_INCREMENT
le colonne così a lungo come si utilizza un'altra colonna come chiave.
Dato customer[id identity, email varchar(30), count int]
si potrebbe 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)
.Significato, ri-utilizzare l'id di un record esistente, è possibile utilizzare null altrimenti.
Vedi anche https://stackoverflow.com/a/18819879/14731 per un portatile modo per inserire o aggiornare a seconda se una riga già esistente.
1.UNIRE IN audit_transaction_ids (uuid, tempo) KEY(id) VALUES(TRANSACTION_ID(), NOW())
Se si desidera inserire una nuova riga, utilizzare:INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())
MERGE
senza impostare il valore per la colonna ID
non ha senso se ID
viene utilizzato come chiave, perché in quel modo non avrebbe mai potuto (anche in teoria) un aggiornamento righe esistenti.Quello che si potrebbe fare è usare un'altra chiave di colonna (nel caso di sopra, non c'è colonna che potrebbe essere utilizzato).Vedere la documentazione per MERGE
per ulteriori dettagli.
2.Invocando l'UNIONE in una riga esistente alterare "il tempo"
Non so se ti riferisci al fatto che il valore della colonna "tempo" è alterato.Questo è il comportamento previsto, se si utilizza MERGE ... VALUES(.., NOW())
, perché il MERGE
istruzione dovrebbe aggiornare la colonna.
O forse vuoi dire che le vecchie versioni di H2 restituito valori diversi all'interno della stessa transazione (a differenza di altri database, che restituiscono lo stesso valore all'interno della stessa transazione).Questo è vero, però con la versione H2 1.3.155 (2011-05-27) e, più tardi, questa incompatibilità è stato risolto.Vedere anche il change log:"CURRENT_TIMESTAMP() e così via ora restituiscono lo stesso valore all'interno di una transazione." Sembra che questo non è il problema nel tuo caso, perché non sembrano utilizzare la versione 1.3.155 (il messaggio di errore [90081-155] comprende la costruzione / numero di versione).
Altri suggerimenti
Risposta Breve:
UNIRE IN AUDIT_TRANSACTION_IDS (uuid, tempo) CHIAVE (uuid, tempo) VALORI (TRANSACTION_ID(), NOW());
po ' di prestazioni di punta:assicurarsi uuid è indicizzato
Risposta Lunga:
MERGE
è fondamentalmente un UPDATE
che INSERT
s quando nessun record trovato per essere aggiornati.
Wikipedia dà una più concisa, standardizzato sintassi di UNIRE ma è necessario fornire il proprio aggiornamento e di inserimento.(Se questo sarà supportato in H2 o meno, non sta a me rispondere)
Così come si aggiorna un record utilizzando MERGE
in H2?Si definisce una chiave per essere guardato, se si è constatato che si aggiorna la riga (con i nomi di colonna di fornitura, e si può definire DEFAULT
qui, per ripristinare le colonne per i suoi valori di default), altrimenti si inserisce la riga.
Ora, qual è Null
? Null
significa sconosciuto, non trovato, indefinito, qualcosa che non è quello che stai cercando.
Che è il motivo per cui Null
funziona come chiave per essere guardato per.Perché significa che il record non è stato trovato.
MERGE INTO tabella1 (id, col1, col2) KEY(id) VALUES (Null, 1, 2)
Null
ha un valore.SI tratta di un valore.
Ora vediamo di SQL.
MERGE INTO tabella1 (id, col1, col2) KEY(id) (VALORI di DEFAULT, 1, 2)
Che cosa è che questo significhi?A me, dice
Ho questo [DEFAULT, 1, 2], mi trovi un DEFAULT
nella colonna id
,
quindi aggiornare col1
per 1, col2
per 2, se trovato.in caso contrario, inserire di default per id
, Da 1 a col1
, 2 a col2
.
Vedere quello che ho sottolineato lì?Che cosa vuol dire?Che cosa è DEFAULT
?Come si fa a confrontare DEFAULT
per id
?
DEFAULT
è una parola chiave.
Si può fare cose come questa,
MERGE INTO tabella1 (id, col1, timeStampCol) KEY(id) VALUES (Null, 1, Di DEFAULT)
ma non mettere di DEFAULT nella colonna di chiave.