mysql actualiza varias columnas con el mismo ahora ()

87

Necesito actualizar 2 columnas de fecha y hora, y necesito que sean exactamente iguales, usando mysql versión 4.1.20. Estoy usando esta consulta:

mysql> update table set last_update=now(), last_monitor=now() where id=1;

¿Es seguro o existe la posibilidad de que las columnas se actualicen con una hora diferente, debido a las 2 llamadas visibles a now()?
No creo que se pueda actualizar con diferentes valores (creo que internamente mysql llama now()solo una vez por fila o algo similar), pero no soy un experto, ¿qué piensas?

Actualización: la segunda pregunta se extrajo aquí .

Radu Maris
fuente
1
Le sugiero que elimine su segunda pregunta de aquí y, finalmente, la vuelva a publicar en una publicación separada.
Cœur

Respuestas:

144

Encontré una solución:

mysql> UPDATE table SET last_update=now(), last_monitor=last_update WHERE id=1;

Encontré esto en MySQL Docs y después de algunas pruebas funciona:

la siguiente declaración establece col2 en el valor actual (actualizado) de col1, no en el valor original de col1. El resultado es que col1 y col2 tienen el mismo valor. Este comportamiento difiere del SQL estándar.

ACTUALIZAR t1 SET col1 = col1 + 1, col2 = col1;

Radu Maris
fuente
¿Hay alguna forma de que esto no funcione? ¿En un procedimiento o usando la combinación con tablas temporales?
Soheil Rahsaz
7

Mysql no es muy inteligente. Cuando desee utilizar la misma marca de tiempo en varias consultas de actualización o inserción, debe declarar una variable.

Cuando usa la now()función, el sistema llamará a la marca de tiempo actual cada vez que la llame en otra consulta.

Olivier
fuente
5

MySQL evalúa ahora () una vez por declaración cuando la declaración comienza a ejecutarse. Por lo tanto, es seguro tener múltiples llamadas ahora visibles () por declaración.

select now(); select now(), sleep(10), now(); select now();
+---------------------+
| now()               |
+---------------------+
| 2018-11-05 16:54:00 |
+---------------------+
1 row in set (0.00 sec)

+---------------------+-----------+---------------------+
| now()               | sleep(10) | now()               |
+---------------------+-----------+---------------------+
| 2018-11-05 16:54:00 |         0 | 2018-11-05 16:54:00 |
+---------------------+-----------+---------------------+
1 row in set (10.00 sec)

+---------------------+
| now()               |
+---------------------+
| 2018-11-05 16:54:10 |
+---------------------+
1 row in set (0.00 sec)
Rich Andrews
fuente
1

Puede almacenar el valor de ahora () en una variable antes de ejecutar la consulta de actualización y luego usar esa variable para actualizar los campos last_updatey last_monitor.

Esto garantizará que ahora () se ejecute solo una vez y que se actualice el mismo valor en las dos columnas que necesita.

Sachin Shanbhag
fuente
1

Puede poner el siguiente código en el valor predeterminado de la columna de marca de tiempo:, CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPpor lo tanto, al actualizar, las dos columnas toman el mismo valor.

Danny
fuente
1
AFAIK "on update" tiene un límite de una columna por tabla, por lo que no se puede establecer en ambas columnas.
Radu Maris
0

Si realmente necesita estar seguro de que now()tiene el mismo valor, puede ejecutar dos consultas (que también responderán a su segunda pregunta, en ese caso lo está preguntando update last_monitor = to last_updatepero last_updateaún no se ha actualizado)

podrías hacer algo como:

mysql> update table set last_update=now() where id=1;
mysql> update table set last_monitor = last_update where id=1;

de todos modos, creo que mysql es lo suficientemente inteligente como para pedir now()solo una vez por consulta.

sathia
fuente
¿Qué tal las dos actualizaciones? ¿también cree que mysql es lo suficientemente inteligente como para combinarlos en una sola declaración? porque no lo hará.
Rafael Herscovici
0

Hay 2 formas de hacerlo;

Primero , le aconsejaría que declare now () como una variable antes de inyectarla en la declaración sql. Digamos;

var x = now();
mysql> UPDATE table SET last_update=$x, last_monitor=$x WHERE id=1;

Lógicamente, si desea una entrada diferente para last_monitor, agregará otra variable como;

var y = time();
mysql> UPDATE table SET last_update=$x, last_monitor=$y WHERE id=1;

De esta manera, puede usar las variables tantas veces como sea posible, no solo en declaraciones mysql sino también en el lenguaje de programación del lado del servidor (como PHP) que está usando en su proyecto. Recuerde que estas mismas variables se pueden insertar como entradas en un formulario en el front-end de la aplicación. Eso hace que el proyecto sea dinámico y no estático.

En segundo lugar si now () indica la hora de la actualización, utilizando mysql puede etiquetar la propiedad de la fila como una marca de tiempo. Cada vez que se inserta o se actualiza una fila, la hora también se actualiza.

Wahinya Brian
fuente
Bienvenido a SO. Aunque esta es una solución al problema, en realidad no responde a la pregunta: "¿Hay algún problema al utilizar la función NOW () incorporada de mysql?". También sugieres usar un lenguaje externo sobre el que el cartel no tenga control. No estoy seguro de su segunda sugerencia (mi recuerdo de mysql no es tan detallado) pero apoyarlo con enlaces a algunos documentos / ejemplos daría mucha más credibilidad.
Martin
En mi segunda sugerencia, si ahora () se va a usar como marca de tiempo cada vez que se realiza una actualización, el siguiente enlace puede ayudar; alvinalexander.com/mysql/… En mi primera sugerencia, cada columna en una tabla mysql es independiente. Por lo tanto, la entrada de datos (como usar una variable en la pregunta anterior) se realiza de forma independiente. Sin embargo, puede comparar y contrastar datos en diferentes columnas utilizando operadores como>, <, =,! =,! <. Esto simplemente significa que no puede ingresar datos en las columnas de esta manera; mysql> conjunto de tablas de actualización last_update = last_monitor = now () donde id = 1;
Wahinya Brian