MySQL
 Computer >> コンピューター >  >> プログラミング >> MySQL

MySQLのUPDATEでdatetime=NOW()を使うと、更新されたすべての行は同じ日付・時刻になる?

MySQLでUPDATE文を実行する際にdatetime = NOW()と指定した場合、更新されたすべての行が同じ日付・時刻になるのかどうか、気になったことはありませんか?結論から言うと、使用する関数によって挙動が異なります。この記事では、NOW()SYSDATE()の違いを実際の例を交えて詳しく解説します。

NOW()とSYSDATE()の違い

NOW()関数は、ステートメント(SQL文)が実行を開始した時点の時刻を定数として返します。つまり、1つのUPDATE文の中で何行更新しようとも、すべての行に同じ時刻が設定されます。

一方、SYSDATE()関数は、その関数が実際に実行された瞬間の日時を返します(MySQL 5.0.13以降)。ただし、単純なUPDATE文では処理が非常に高速なため、結果としてほぼ同じ時刻になるのが一般的です。

また、トリガーやストアドプロシージャ内でdatetimeカラムをNOW()で更新する場合も、NOW()はトリガーやストアドプロシージャの実行が開始された時刻を返します。

検証用テーブルの作成

それでは、実際にNOW()を使ったUPDATEの動作を確認してみましょう。まず、デモ用のテーブルを作成します。

mysql> create table NowDemo
-> (
-> DueDateTime datetime
-> );
Query OK, 0 rows affected (0.51 sec)

レコードの挿入

次に、INSERTコマンドを使ってテーブルにレコードを挿入します。

mysql> insert into NowDemo values('2018-12-19');
Query OK, 1 row affected (0.15 sec)

mysql> insert into NowDemo values('2018-11-10');
Query OK, 1 row affected (0.20 sec)

mysql> insert into NowDemo values('2017-11-21');
Query OK, 1 row affected (0.09 sec)

レコードの確認

SELECT文ですべてのレコードを確認します。

mysql> select *from NowDemo;

実行結果は以下の通りです。

+---------------------+
| DueDateTime         |
+---------------------+
| 2018-12-19 00:00:00 |
| 2018-11-10 00:00:00 |
| 2017-11-21 00:00:00 |
+---------------------+
3 rows in set (0.00 sec)

ケース1:NOW()を使用した場合

NOW()を使ってdatetimeカラムを更新するクエリは以下の通りです。

mysql> update NowDemo set DueDateTime = now();
Query OK, 3 rows affected (0.12 sec)
Rows matched: 3 Changed: 3 Warnings: 0

SELECTコマンドで更新後の値を確認してみましょう。

mysql> select *from NowDemo;

実行結果を見ると、すべての行に同じ日付・時刻が設定されていることがわかります。

+---------------------+
| DueDateTime         |
+---------------------+
| 2018-12-20 16:10:00 |
| 2018-12-20 16:10:00 |
| 2018-12-20 16:10:00 |
+---------------------+
3 rows in set (0.00 sec)

これは、NOW()がUPDATE文の実行開始時刻を固定値として返すためです。どの行がいつ処理されたかに関わらず、同じステートメント内では常に同一の時刻になります。

ケース2:SYSDATE()を使用した場合

次に、SYSDATE()を使った場合の動作を確認します。

mysql> update NowDemo set DueDateTime = sysdate();
Query OK, 3 rows affected (0.43 sec)
Rows matched: 3 Changed: 3 Warnings: 0

SELECT文でテーブルから更新後の値を確認します。

mysql> select *from NowDemo;

実行結果は以下の通りです。

+---------------------+
| DueDateTime         |
+---------------------+
| 2018-12-20 16:10:35 |
| 2018-12-20 16:10:35 |
| 2018-12-20 16:10:35 |
+---------------------+
3 rows in set (0.00 sec)

この例では、UPDATE文の実行が非常に高速だったため、すべての行に同じ時刻が設定されました。しかし、大量の行を更新する場合や処理に時間がかかる場合は、SYSDATE()は各行が処理される実際の時刻を評価するため、理論上は異なる時刻が設定される可能性があります。

まとめ

  • NOW():ステートメントの実行開始時刻を返すため、1つのUPDATE文で更新したすべての行は必ず同じ日付・時刻になる。
  • SYSDATE():関数が実行された実際の時刻を返すため、処理時間によっては行ごとに異なる時刻になる可能性がある。

監査ログなどで「更新日時」を正確に記録したい場合はSYSDATE()、トランザクション全体で一貫したタイムスタンプが必要な場合はNOW()を使うとよいでしょう。用途に応じて適切な関数を選択することが重要です。

  1. 【MySQL】GROUP BYとHAVING句で同じテーブル内の共通する値を持つ行を抽出する方法

    はじめにMySQLで、同じテーブル内に登録された複数の行の中から、特定の値が繰り返し登場するデータを抽出したいケースはよくあります。たとえば、「同じIDが何度も出現しているレコードを見つけたい」といった場合です。こうした処理には、GROUP BY句とHAVING句を組み合わせるのが効果的です。本記事では、実際のSQLコードと実行結果をもとに、その手順をわかりやすく解説します。1. サンプルテーブルを作成するまず、動作確認用のテーブルを作成しましょう。ここでは「Id」と「Name」の2つのカラムを持つシンプルなテーブルを用意します。mysql> create table DemoTable

  2. MySQLで複数のデータを一度に挿入する方法を解説

    MySQLでは、INSERT文を複数回実行しなくても、1つのINSERT文で複数行のデータを同時にテーブルへ挿入できます。この方法を使うと、コードが簡潔になるだけでなく、データベースとの通信回数が減るため、大量のデータを挿入する際のパフォーマンス向上にもつながります。 複数行を挿入するための基本構文 複数のレコードを一度に挿入するには、VALUES句の後に値のセットをカンマで区切って並べます。構文は以下のとおりです。 INSERT INTO テーブル名 VALUES(値1, 値2, .....N), (値1, 値2, .....N), (値1, 値2, .....N), (値1, 値2, ..