Pregunta

He declarado la siguiente tabla para su uso por desencadenantes de auditoría:

CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
  1. El disparador se invocará varias veces en la misma transacción.

  2. La primera vez que se invoca el disparador, quiero que inserte una nueva fila con la transacción actual_id () y la hora.

  3. Las veces posteriores se invoca el desencadenante, quiero que devuelva la "ID" existente (invoco Declary.getGeneratedKeys () a ese fin) sin alterar "uuid" o "tiempo".

El esquema actual parece tener dos problemas.

  1. Cuando invoco MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW()) Yo obtengo: 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. Sospecho que invocar la fusión en una fila existente alterará el "tiempo".

¿Cómo soluciono ambos problemas?

¿Fue útil?

Solución

MERGE es análogo a java.util.Map.put(key, value): Insertará la fila si no existe, y actualizará la fila si lo hace. Dicho esto, aún puedes fusionarte en una mesa que contiene AUTO_INCREMENT columnas siempre que use otra columna como clave.

Dado customer[id identity, email varchar(30), count int] tú podrías 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). Es decir, reutilizar la identificación Si existe un registro, use nulo de otra manera.

Ver también https://stackoverflow.com/a/18819879/14731 Para una forma portátil de insertar o actualizar dependiendo de si ya existe una fila.


1. Fusionar en audit_transaction_ids (UUID, Time) Key (ID) Valores (Transaction_id (), ahora ()))

Si solo desea insertar una nueva fila, use:INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())

MERGE sin establecer el valor para la columna ID no tiene sentido si ID se usa como clave, porque de esa manera nunca podría (incluso en teoría) actualizar las filas existentes. Lo que podría hacer es usar otra columna clave (en el caso anterior, no hay una columna que pueda usarse). Ver la documentación para MERGE para detalles.

2. Invocar la fusión en una fila existente alterará el "tiempo"

No estoy seguro de si hablas sobre el hecho de que el valor de la columna 'tiempo' está alterado. Este es el comportamiento esperado si usa MERGE ... VALUES(.., NOW()), porque el MERGE Se supone que la declaración actualiza esa columna.

O tal vez quiere decir que las versiones anteriores de H2 devolvieron diferentes valores dentro de la misma transacción (a diferencia de la mayoría de las otras bases de datos, que devuelven el mismo valor dentro de la misma transacción). Esto es cierto, sin embargo, con H2 versión 1.3.155 (2011-05-27) y más tarde, esta incompatibilidad es fija. Ver también el Registro de cambio: "Current_timestamp () y así sucesivamente devuelve el mismo valor dentro de una transacción". Parece que este no es el problema en su caso, porque parece usar la versión 1.3.155 (el mensaje de error [90081-155] incluye el número de compilación / versión).

Otros consejos

Respuesta corta:

Fusionarse en audit_transaction_ids (uuid, time) key (uuid, time) valores (transaccion_id (), ahora ());

Poco consejo de rendimiento: asegúrese de que UUID esté indexado

Respuesta larga:

MERGE es básicamente un UPDATE cual INSERTS cuando no se actualiza ningún registro.

Wikipedia ofrece una sintaxis estandarizada más concisa deUNIR Pero debe proporcionar su propia actualización e insertar. (Si esto será compatible en H2 o no, no es mío para responder)

Entonces, ¿cómo se actualiza un registro usando MERGE en H2? Defina una clave para ser revelada, si se encuentra que actualiza la fila (con los nombres de la columna que suministra, y puede definir DEFAULT Aquí, para restablecer sus columnas a sus valores predeterminados), de lo contrario, inserta la fila.

Ahora que es Null? Null significa desconocido, no encontrado, indefinido, cualquier cosa que no sea lo que estás buscando.

Es por eso que Null Funciona como clave para ser admirado. Porque significa que el registro no se encuentra.

Fusionar en los valores de la tecla (ID, COL1, Col2) (ID) (NULL, 1, 2)

Null tiene un valor. Es un valor.

Ahora veamos tu SQL.

Fusionar en los valores de la tecla (ID, COL1, COL2) (ID) de la Tabla1 (ID, COL1, COL2) (predeterminado, 1, 2)

¿Qué está implicando eso? Para mí, dice que tengo este [predeterminado, 1, 2], Encuéntrame un DEFAULT en columna id, luego actualizar col1 a 1, col2 a 2, si se encuentra. De lo contrario, inserte predeterminado a id, 1 a col1, 2 a col2.

¿Ves lo que enfaticé allí? ¿Y eso que significa? Que es DEFAULT? ¿Cómo se compara? DEFAULT a id?

DEFAULT es solo una palabra clave.

Puedes hacer cosas como,

Fusionar en la Tabla1 (ID, COL1, Timestampcol) Key (ID) Valores (NULL, 1, predeterminado)

Pero no ponga predeterminado en la columna clave.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top