皆さんはDEFAULT CURRENT_をご存じでしょうか? この指定を行ったカラムはINSERTやUPDATEを行った際に自動更新をしてくれるようになります。特に忘れがちなcreated_
そんな事情もあり、created_
この機能自体は昔からMySQLにある機能なので、知っている人も多いと思いますが、入れておくと非常に安心できる守護神のような存在なので、知っておいて損はありません。
検証環境
今回はMySQL 8.
version: '3.8'
services:
mysql84:
image: mysql:8.4
container_name: mysql-84
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: testdb
ports:
- "3307:3306" # 8.4 は 3308 に割り当て
command: >
mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./mysql84-init:/docker-entrypoint-initdb.d
ファイル構成は以下の通りで、各initディレクトリの下には初期化のSQLを置いてあります。
.
├─ docker-compose.yml
└─ mysql84-init/
└─ 01-table.sql
01-table.
CREATE TABLE item_count (
id INT AUTO_INCREMENT PRIMARY KEY,
count INT DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
上記の用意を行ったうえで、以下のコマンドで起動します。
docker compose up -d
今回はローカルのmysqlクライアントを使用しないで、docker内のmysqlクライアントを使用してMySQLに接続するようにしています。使用するコマンドは以下のようになります。
docker exec -it mysql-84 mysql -uroot -proot testdb # 8.4へ
以下のクエリを実行して同様の結果が得られていれば大丈夫です。
mysql> select * FROM item_count; Empty set (0.00 sec)
挙動を確認してみる
さっそくですが、item_
INSERT INTO item_count (count) VALUES (1);
SELECT * FROM item_count;
実行すると以下のような結果が得られます。created_
mysql> SELECT * FROM item_count; +----+-------+---------------------+---------------------+ | id | count | created_at | updated_at | +----+-------+---------------------+---------------------+ | 1 | 1 | 2025-11-21 04:06:23 | 2025-11-21 04:06:23 | +----+-------+---------------------+---------------------+ 1 row in set (0.00 sec)
続けてupdateをしてみましょう。countのカラムを1から2に更新してみます。
mysql> UPDATE item_count SET count=count+1 WHERE id = 1; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from item_count; +----+-------+---------------------+---------------------+ | id | count | created_at | updated_at | +----+-------+---------------------+---------------------+ | 1 | 2 | 2025-11-21 04:06:23 | 2025-11-21 04:07:40 | +----+-------+---------------------+---------------------+ 1 row in set (0.00 sec)
updated_
ここからですが、実はこのupdaated_DEFAULT CURRENT_は、1個だけではなく複数のカラムで指定することができます。
それでは実際にlatest_
mysql> ALTER TABLE item_count ADD COLUMN latest_viewed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> select * from item_count; +----+-------+---------------------+---------------------+---------------------+ | id | count | created_at | updated_at | latest_viewed_at | +----+-------+---------------------+---------------------+---------------------+ | 1 | 2 | 2025-11-21 04:06:23 | 2025-11-21 04:07:40 | 2025-11-21 04:10:50 | +----+-------+---------------------+---------------------+---------------------+ 1 row in set (0.00 sec)
DEFAULT値を指定していたので、ALTER TABLE文が実行された時刻が入っています。後追いでALTER TABLEW文を実行した場合に同じ値が並ぶことになるので、そこは考慮して実装しましょう。
さらに、ここからUPDATE文を実行してみましょう。
mysql> update item_count SET count = count + 1 WHERE id = 1; Query OK, 1 row affected (0.02 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from item_count; +----+-------+---------------------+---------------------+---------------------+ | id | count | created_at | updated_at | latest_viewed_at | +----+-------+---------------------+---------------------+---------------------+ | 1 | 3 | 2025-11-21 04:06:23 | 2025-11-21 04:11:34 | 2025-11-21 04:11:34 | +----+-------+---------------------+---------------------+---------------------+ 1 row in set (0.00 sec)
このように、2カラムとも同じ値が入っていることがわかります。2カラム以上設定できるようになっているので、updated_
TIMESTAMP型はマイクロ秒に対応しているので、もっと細かい値を取りたい場合は、以下のようにTIMESTAMP型に指定を入れて使用しましょう。
mysql> ALTER TABLE item_count ADD COLUMN latest_count_at TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> SELECT * FROM item_count; +----+-------+---------------------+---------------------+---------------------+----------------------------+ | id | count | created_at | updated_at | latest_viewed_at | latest_count_at | +----+-------+---------------------+---------------------+---------------------+----------------------------+ | 1 | 3 | 2025-11-21 04:06:23 | 2025-11-21 04:11:34 | 2025-11-21 04:11:34 | 2025-11-21 04:16:23.172051 | +----+-------+---------------------+---------------------+---------------------+----------------------------+ 1 row in set (0.00 sec)
ちなみに以下のようにTIMESTAMP型でマイクロ秒を指定した場合に、DEFAULT値やON UPDATEの記載の際のマイクロ秒の指定の数字がずれていると、ALTER TABLE文に失敗するので注意しましょう。
mysql> ALTER TABLE item_count ADD COLUMN latest_count_at1 TIMESTAMP(4) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6); ERROR 1067 (42000): Invalid default value for 'latest_count_at1'
上記のエラーはDEFAULT値の値が合っていないことを示していて、下記のエラーはON UPDATE句が一致していないことを示しています。
mysql> ALTER TABLE item_count ADD COLUMN latest_count_at1 TIMESTAMP(4) DEFAULT CURRENT_TIMESTAMP(4) ON UPDATE CURRENT_TIMESTAMP(6); ERROR 1294 (HY000): Invalid ON UPDATE clause for 'latest_count_at1' column
またこのオプションを指定していても、SQLで直接時刻を指定をすることで上書きすることもできます。
mysql> UPDATE item_count
-> SET updated_at = '2025-01-01 00:00:00'
-> WHERE id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * FROM item_count;
+----+-------+---------------------+---------------------+---------------------+----------------------------+
| id | count | created_at | updated_at | latest_viewed_at | latest_count_at |
+----+-------+---------------------+---------------------+---------------------+----------------------------+
| 1 | 3 | 2025-11-21 04:06:23 | 2025-01-01 00:00:00 | 2025-11-21 04:32:34 | 2025-11-21 04:32:34.996611 |
+----+-------+---------------------+---------------------+---------------------+----------------------------+
1 row in set (0.00 sec)
DBをSQLで操作するうえでは基本的に非常に便利なのですが、ORMが予期せずUPDATE文を発火する場合や、すでに持っている値の更新などが漏れる場合があり、ORMとの相性を見て導入を検討した方が良いでしょう。
まとめ
今回はDEFAULT CURRENT_の紹介を行いました。
最初にも書きましたが、created_
ORMを使用して開発しているときは、アプリケーションが更新処理に対してcreated_