mysql atualizar várias colunas com o mesmo agora ()

87

Preciso atualizar 2 colunas de data e hora e preciso que sejam exatamente iguais, usando o mysql versão 4.1.20. Estou usando esta consulta:

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

É seguro ou há uma chance de que as colunas sejam atualizadas com tempos diferentes, por causa das 2 chamadas visíveis para now()?
Não acho que possa ser atualizado com valores diferentes (acho que internamente o mysql chama now()apenas uma vez por linha ou algo semelhante), mas não sou um especialista, o que você acha?

Atualização: a segunda questão foi extraída aqui .

Radu Maris
fonte
1
Eu sugiro que você remova sua segunda pergunta daqui e, eventualmente, a repasse em uma postagem separada.
Cœur

Respostas:

144

Encontrou uma solução:

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

Eu encontrei isso no MySQL Docs e depois de alguns testes, funciona:

a instrução a seguir define col2 com o valor col1 atual (atualizado), não o valor col1 original. O resultado é que col1 e col2 têm o mesmo valor. Este comportamento difere do SQL padrão.

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

Radu Maris
fonte
Existe alguma maneira de isso não funcionar? Em um procedimento ou usando junção com tabelas temporárias?
Soheil Rahsaz
7

Mysql não é muito inteligente. Quando você deseja usar o mesmo carimbo de data / hora em várias atualizações ou consultas de inserção, você precisa declarar uma variável.

Ao usar a now()função, o sistema chamará o carimbo de data / hora atual sempre que você chamá-lo em outra consulta.

Olivier
fonte
5

O MySQL avalia now () uma vez por instrução quando a instrução começa a ser executada. Portanto, é seguro ter várias chamadas now () visíveis por instrução.

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
fonte
1

Você pode armazenar o valor de um now () em uma variável antes de executar a consulta de atualização e então usar essa variável para atualizar os campos last_updatee last_monitor.

Isso garantirá que o now () seja executado apenas uma vez e o mesmo valor seja atualizado nas duas colunas de que você precisa.

Sachin Shanbhag
fonte
1

Você pode colocar o seguinte código no valor padrão da coluna de carimbo de data / hora: CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMPportanto, na atualização, as duas colunas têm o mesmo valor.

Danny
fonte
1
AFAIK "na atualização" tem um limite de uma coluna por tabela, portanto, não pode configurá-lo para ambas as colunas.
Radu Maris
0

Se você realmente precisa ter certeza de que now()tem o mesmo valor, pode executar duas consultas (que responderão à sua segunda pergunta também, nesse caso você está perguntando, update last_monitor = to last_updatemas last_updateainda não foi atualizado)

você poderia fazer algo como:

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

de qualquer forma, acho que o mysql é inteligente o suficiente para pedir now()apenas uma vez por consulta.

sathia
fonte
Que tal as duas atualizações? você também acha que o mysql é inteligente o suficiente para combiná-los em uma instrução? porque não vai.
Rafael Herscovici
0

Existem 2 maneiras de fazer isso;

Primeiro , eu aconselharia você a declarar now () como uma variável antes de injetá-lo na instrução sql. Digamos;

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

Logicamente, se você deseja uma entrada diferente para last_monitor, então você adicionará outra variável como;

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

Desta forma, você pode usar as variáveis ​​quantas vezes puder, não apenas em instruções mysql, mas também na linguagem de script do lado do servidor (como o PHP) que você está usando em seu projeto. Lembre-se de que essas mesmas variáveis ​​podem ser inseridas como entradas em um formulário no front-end do aplicativo. Isso torna o projeto dinâmico e não estático.

Em segundo lugar, se now () indica a hora da atualização, então usando mysql você pode decalre a propriedade da linha como um timestamp. Cada vez que uma linha é inserida ou atualizada, a hora também é atualizada.

Wahinya Brian
fonte
Bem-vindo ao SO. Embora esta seja uma solução para o problema, ela realmente não responde à pergunta que é "Existe um problema ao usar a função NOW () integrada do mysql?". Além disso, você sugere o uso de uma linguagem externa sobre a qual o autor da postagem pode não ter controle. Não tenho certeza da sua segunda sugestão (minha lembrança do mysql não é tão detalhada), mas apoiá-la com links para alguns documentos / exemplos daria muito mais credibilidade.
Martin
Em minha segunda sugestão, se now () for usado como um carimbo de data / hora sempre que qualquer atualização ocorrer, o link a seguir pode ajudar; alvinalexander.com/mysql/… Na minha primeira sugestão, cada coluna em uma tabela mysql é independente. Portanto, a entrada de dados (como usar uma variável na questão acima) é feita de forma independente. No entanto, você pode comparar e contrastar dados em colunas diferentes usando operadores como>, <, =,! = ,! <. Isso simplesmente significa que você não pode inserir dados nas colunas como este; mysql> update table set last_update = last_monitor = now () onde id = 1;
Wahinya Brian de