概要
- MySQL 5.6.26 では時間式の限界は
34 22:59:59
のようです。-
リファレンスに
838:59:59
の記載があるため、その通りの挙動です。
-
リファレンスに
-
INTERVAL 35 DAY
とかで回避。
再現した環境
MySQL 5.6.19 と 5.6.26 と 5.6.30
起きた事
MySQL の datetime 型から SUBTIME 関数で引き算をやろうとした結果、Python-MySQL から _mysql_exceptions.Warning: Truncated incorrect time value: '60 00:00'
と怒られました。MySQL クライアントで直接入力してる限りエラーは見当たらないんだけど・・・と思っていたのですが、中身をよく見るとおかしなことが起きていました。
SELECT SUBTIME('2007-12-31 00:00:00', '60 00:00');
+--------------------------------------------+
| SUBTIME('2007-12-31 00:00:00', '60 00:00') |
+--------------------------------------------+
| 2007-11-26 01:00:01 |
+--------------------------------------------+
1 row in set, 1 warning (0.00 sec)
ここで求められる正解は 2007-11-01 00:00:00
のはずだけど、実際には 2007-11-26 01:00:01
が返却されている。
ここで MySQL の関数リファレンスを調べると
SUBTIME(expr1,expr2)
SUBTIME() は、expr1 と同じ書式で表現される expr1 と expr2 を返します。expr1 は時間または日付時間式であり、expr2 は時間式です。
とありますが、時間式とされている方に限界がありそうです。恐らく '34 22:59:59'
が限界。
SELECT SUBTIME('2007-12-31 00:00:00', '34 22:00');
SELECT SUBTIME('2007-12-31 00:00:00', '34 23:00');
+--------------------------------------------+
| SUBTIME('2007-12-31 00:00:00', '34 22:00') |
+--------------------------------------------+
| 2007-11-26 02:00:00 |
+--------------------------------------------+
1 row in set (0.00 sec)
+--------------------------------------------+
| SUBTIME('2007-12-31 00:00:00', '34 23:00') |
+--------------------------------------------+
| 2007-11-26 01:00:01 |
+--------------------------------------------+
1 row in set, 1 warning (0.00 sec)
概ね想定通りの結果です。せっかくなので足し算も試してみよう
SELECT ADDTIME('2007-12-31 00:00:00', '60 00:00');
+--------------------------------------------+
| ADDTIME('2007-12-31 00:00:00', '60 00:00') |
+--------------------------------------------+
| 2008-02-03 22:59:59 |
+--------------------------------------------+
1 row in set, 1 warning (0.00 sec)
そうなると思ってた。ADDTIME
や SUBTIME
に問題があるのではなくて、expr2
の方に入るべき時間式の方に問題がありそう。
追記
コメント欄で教えていただきました。TIME型のリファレンス にバッチリ記載されています。
TIME 値の範囲は、'-838:59:59' から '838:59:59' です
rryu さんありがとうございます。
どうやって回避するか?
INTERVAL
でチマチマ回避することにします。
SELECT '2007-12-31 00:00:00' - INTERVAL 60 DAY;
+-----------------------------------------+
| '2007-12-31 00:00:00' - INTERVAL 60 DAY |
+-----------------------------------------+
| 2007-11-01 00:00:00 |
+-----------------------------------------+
1 row in set (0.01 sec)
問題ない。