@kyanny's blog

革命は金銭ではない - 孫文

TIL: 数値をあえて文字列型で保存することがある

列1 列2 列3 列4
eb2c0958-991c-5f26-4d99-8214518fbb8a a 20000 5000
66a08082-ebd0-6de2-c4e8-6388df00e4e5 b 20000 5000

このようなデータを持つ CSV ファイルをパースして RDBMS のテーブルに保存する。列2の値がaならテーブルAに、bならテーブルBに保存する。

テーブルAの各行は、列3と列4の値を数値計算に利用する。テーブルBの各行は、行が存在することにのみ意味があり、列3も列4も数値計算には利用しない。

このような前提で、テーブルBの列3と列4のデータ型が文字列型になっていた。テーブルAの列3と列4は数値型なのにだ。

テーブルA

列名 データ型
列1 text
列2 text
列3 int
列4 int

テーブルB

列名 データ型
列1 text
列2 text
列3 text
列4 text

CSV ファイルの形式上は同種のデータを保存するのだから、両方のテーブルでデータ型は一致しているべきではないのか?

と疑問に思ったので質問すると、「テーブルBの列3と列4は数値計算に用いないため、あえて文字列型にしている」という回答で、なるほどと思った。動的型付けの言語ではこういう設計はしないかもね、とも*1

文字列型の列に数値が入っているとき、それを用いて数値計算するためには型を変換しなければならない。 SQL であれプログラミング言語であれ、もし実際に型変換をした上で計算するようなコードを書けば、明らかに目立つ。それが狙いだ、と解釈した。

全く利用するあてのないデータならテーブルに取り込まなければよいのでは?とも思ったが、将来必要にならないとも限らないし、スナップショットとして完全なデータを保存したい気持ちもわかる。テーブルAと比べてテーブルBの列が少なければ少ないで、なぜ列を減らしたのか?という疑問に繋がる。

折衷案として、不要なデータでも取り込んでおくが、そのデータを意味のある計算に用いるミスを犯しにくくするためにあえて文字列型で保存する、という設計には一理あり、現実的だと思った*2

*1:言語特性というよりは設計者の思想による部分が大きいとは思う。ちなみにこのテーブルのデータは主に Go 言語から利用する

*2:テーブル定義を見ただけでは意図に気付きづらく、誤りであると誤解しやすいので、コメント等で「数値計算に用いないようにあえて文字列型にしている」と書き添えてあるとよい、とフィードバックした