どうも、最近スキー板を買った人です
緊急事態宣言出てるんですけどね…w
今日は久しぶりにネタを発見したのでそれについて書いていこうと思います
#文字列日付
日付を文字列型(varcharやtext)で扱ってしまっている、ということです
これ結構見かけるので、一部界隈で流行っているのかもしれません
###何が悪いの?
日付型であれば問題にならなかったことが文字列型だと発生する可能性があります
###問題
- 日付の計算ができない
文字列型だとそのままで計算することができません
int型に変換して無理にやろうとすると…
「2020/12/31に1を足したら、2020/12/32になった」
のようなことが発生します
そもそも30日の月と31日の月を定義するのもめんどくさい上に、うるう年のような計算も入れなければなりません
そのため、文字列型で日付の計算をしようとした場合、結局日付型に直してから計算をするはめになります
で、計算が終わったら日付型を文字列型に直してinsertする…というようなことが発生します
(うるう秒に関しては対応していないDBMSも多いようですが)
- 時差の変換ができない
日付型には、どこの国の時間を使うかが指定できます
が、文字列型だとこんな芸当はできません
これも結局日付型に直して計算する必要があります
- 日付型より柔軟性が無い
例えば、文字列型だと「202013」のような文字列がinsertされてしまいます
これを避けるために下2桁を抽出し、1~12に一致する場合のみinsertを許す、というcheck制約を追加したとします
しかし、もし全ての月を28日にし余った日付を13月にする、という仕組みが世界的に導入されてしまった場合、そのcheck制約は意図に反したものになってしまいます
世界的にこの仕組みが導入されるのであれば、各DBMSはそれ相応の対応をするはずです(互換性のある型を作ったりする等)
文字列型で扱っていると、その恩恵を全く受けることができなくなってしまいます
###原因
なぜこんなことが起こってしまうのか、考えてみました
- フォーマットがめんどくさそうだから使わない
確かに、日付型はフォーマット周りがちょっとめんどくさいです
が、逆に言えば自分の好きなフォーマットでデータを格納できる、ということなのでこれは良いことだと思います
特に指定がなければデフォルトのフォーマットを使ってしまいましょう
- 日付型にするメリットがわからない
あまり日付を扱ったことが無いのであればわかりますが、これまで説明した内容で日付型のメリットをわかって頂けたと思います
#解決方法
- 日付を扱うときは日付型を使う
これだけで文字列型で発生していた問題を解決することができます
#ちょっとおまけ
今回は日付を文字列型として扱ってしまう、という例を見てきましたが、日付をint型で扱うこともあるようです
データ型の選択肢を誤る、異常な制約を掛けてしまう、ということがかなり起こっているようです
例えば、number型(numeric型)のようなものの場合、小数点より右側を何桁までにするかは重要ですが、小数点より左側を何桁までにするかはあまり重要ではありません
にもかかわらず、整数部にまで桁数の制限を掛けたりしてしまっているようです
varchar型やtext型でも、「とりあえず1000くらいで制限をかけとこ」って人が多いようです
確かに、1レコードが格納できる容量というのは決まっているためある程度制限を掛けたほうが良いという意見もわかりますが、これをやってしまうと別の問題が発生します
画面で1000文字までの入力しか受け付けず、DBでも1000文字までしか受け付けないようにしているとします
このとき、画面側で3000文字まで入力を受け付けたい、となったときはDBのカラム定義変更を行う必要が出てきてしまいます
これは、DBで異常な制約を掛けてしまったせいで画面とDBが密結合になってしまっている例です
画面で受け付けるデータの種類を増やしたい、という例であればDBのカラム追加は正当なものになり得ますが、文字数に関しては本来不要だった作業が増えてしまっています
そのため、文字列型や実数型で異常な制約を掛けるのはやめましょう
基本的には、制限を掛けないか、デフォルトの値を使いましょう
データの生成をデバックするのはアプリケーションの仕事です
倉庫に失敗作が入っているからといって、それを倉庫のせいにしないでください
(勿論、データの不整合を防ぐための外部キーは必要です)
#まとめ
- 黙って日付型を使え
- 意味もなく制限を掛けるな
どうだったでしょうか
無意味なことはやめて、意味のあることをやりましょう