0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

小ネタ 存在が耐えきれないほど軽い`date`(MySQL)

Posted at

「分かりにくい命名はやめましょう」「分かりやすいSQLを書きましょう」ということの例示をしていたら、MySQLが謎の挙動をしたので少しビビったという話。

なにが起きたか

id date
1 2001-01-01
2 2005-05-05

↑のテーブルを念頭に↓を紹介していた。

ビビった部分抜粋
-- まず、お手本のSQLを用意した(WHERE句を抜粋。分かりやすさのために一部修正)
WHERE date BETWEEN '2000-01-01' AND '2003-03-03';

-- そこからちょっとだけ分かりにくい(諸説あり)文を用意したが、一番最初のdateを消し忘れていた。でも普通に動いた
WHERE date '2000-01-01' <= date AND date <= '2003-03-03';
-- もちろんこれも動く
WHERE '2000-01-01' <= date AND date <= '2003-03-03';

あってもなくてもいい根無草のdateが出現してしまった。
「WHERE date という文がNULL判定しているんですか?」「キャストしてますか?」といった推測が入り乱れ、当の本人はめちゃくちゃ焦りながら「持ち帰って検討します」をした。

なぜそんな動きをしたか

意図せず、日付リテラルの型の明示date '2000-01-01'の文になっており、dateはあってもなくても変わらない動作をするので。

標準 SQL では、型キーワードと文字列を使用して時間リテラルを指定する必要があります。 キーワードと文字列の間の空白はオプションです。(中略)
MySQL は認識しますが、標準 SQL とは異なり、type キーワードは必要ありません。

全部ほぼ同じ意味のリテラル
-- よく見る普通の日付リテラル
'2000-01-01'
-- DATE型であることを明示。くっつけるパターン
date'2000-01-01'
-- DATE型であることを明示。空白を挟むパターン ←今回はこれ ←混乱する(※個人の感想)
date '2000-01-01'

すべての原因

MySQLのキーワードであるdateをカラム名として使ったのが悪い。

dateという名前のカラムはキーワードだが予約済みではないので、識別子として使えるが、使わない方がいい。」
という一般論を紹介しようとしたら、偶然にもはっきりとした理由を示すことができた。
識別子の大文字小文字を区別しない環境においては日付リテラルの型の明示 DATE 'str' の他にも 関数 DATE() 等とややこしいのでダメ)

自戒

日付型、時間型だけでも、今回の「寛容な」型の明示の他に「世話を焼いてくれる」変換があったりするが、それらとちゃんと向き合ってクエリを書こう。(自戒)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?