MySQL 数値と文字列が混在する場合のデータ型

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 504

Take_it

score 102

MySQLにおいて、数値を格納するカラムがあります。
通常であれば、桁数的にTINYINTのUNSIGNEDで十分足りる感じです。

ところがここに、一部、文字列を格納する必要があります。
この場合、INT系(と言っていいのか?)のデータ型は使えなくなるので、VARCHARあたりにしようかと思うのですが。

INSERTやUPDATEの際に数値データであっても文字列として扱うようにする等、まぁ気を付けるべきところは気を付けるとして、データベースのパフォーマンス上、やはり有意な差が生まれてしまうものでしょうか?

文字列で扱わなければならない場合のみ、テーブルを分けるという方法もできなくはないのですが、その方が好ましいのでしょうか?

===追記===
質問の仕方が悪かったかもしれません。

個人別データを記述したテーブルAには、所属する部署コードと適用される勤務シフトコードのカラムがあります。

部署データは、INT UNSIGNED AI でコードを生成されたテーブルになります。

勤務シフトデータは、部署データのコードをキーに設定したテーブルです。

つまり、部署ごとに勤務シフトが一応決まっていて、個人別データにおいて部署コードと勤務シフトコードのカラムの値は基本的には同一になる設計です。

ところが一部、所属する部署の勤務シフトとは異なる勤務シフトを設定した場合があり、これをどのように扱うかを検討する際に、
勤務シフトデータのテーブルに、部署コードではなく従業員コードをキーに放り込んだデータを用意することとしましたが、当然ですがそれでは部署コードと従業員コードが重複する可能性が排除できません。
そこで、その場合は、なんらかの接頭辞_従業員コードをキーに放り込めば、重複を回避することができます。
但しその場合、キーに使うカラムをINT型ではなくVAECHAR型にする必要があり・・・

という前提のもと、

・VERCHAR型で作った場合と
・(接頭辞をつけるようなデータは入れないように見直して)INT型で作った場合

パフォーマンスにおいて有意な差が出るかどうか、というのが質問です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+2

  • int(tinyint?)のカラムを2列つくって常に数値だけで管理するか
  • 普通にvarcharか
  • 予めデータがきまっているならsetを使うか正規化する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/04 16:00

    多数の回答ありがとうございます。

    intカラムを2列作り、
    ・個別シフトの場合はシフトIDは0とし、従業員IDカラムに従業員ID値を入れる
    ・通常シフトの場合はシフトIDを部署コードとし、従業員IDカラムは0にする
    で制御することにしました。
    どのみち、従業員データテーブル上で、通常シフトを適用するか個別シフトを適用するかをフラグ立ててあるので、どっちを読み出すかはSQL文発行前に判別されていますので。

    ありがとうございました。

    キャンセル

  • 2019/03/04 17:00

    追記の通知が来ていなかったので、反応遅れました。
    既存の実装があるなら、私もそういう選択にすると思います。

    なお、勤務シフトテーブルの主キーが変わるはずなので、INSERT/UPDATE時にシフトID=0のときの従業員IDの値を固定にすることと、そこをSELECTしている部分の見直しを忘れずにした方がいいかもしれません。
    また主キーの定義を周知徹底しておくのと、未来にその制約が維持出来ないとき、作り直すタイミングで必要な情報が整理されているとベターだと思います。

    キャンセル

+2

正規化

でググってきちんと調べるのが問題解決への近道です。
数値型か文字型かでカラムを分けられるのであれば分けましょう。

ズタズタな設計をしてドブに捨てるシステムを作って反省すらしない人を何人も見ています。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

識別子系は長さが変わること、数値でなくなることが多いので、個人的には文字列にしています。
理由は、識別子系は外部から指定されることが多いものだからです。つまりここは外部要件から変更がかかりやすく、内部で勝手に決められない、ということです。外から指定されないものか、未来永劫確実に数字で行けそうなコードの場合のみ、数字で指定します。

なぜそこまで気にするかというと、ココが変わると、設計も実装も大幅に変わり、工数がとんでもなく増えるからです。識別子は多くの場合、どこまでも伝搬されるものなので。文字列は大量に何かを処理する場合、インデックスなどが作られる=ハッシュ値になるはずなので、数字か文字列かでそこまでナイーブになる必要はないと思います。


【追記-1】
上の文章で、数値と数字を混在させていますが、大した意味はありません。個人的には1対1に紐づく前提であれば、どちらでもいいと思っています。MySQLで言えば、intとnumberでは意味が違いますし、intにすればそれなりに小さくなるし速いと予想が出来るからで、識別子としての数字だから文字列にしないといけないか?と言われると必ずしもそうではないからです。ようは算術演算をするから数値という意味付けに実用的な違いがあまりないから、と言えます。

ただし文字列と数値で1対1に紐付かないケースだけはNGです。例えば'00001'と'1'が文字列として両方出現する可能性があり、両者を一意に識別しないといけない場合は、数値だと1にしかしようがないので、それはダメってことです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

数値化や文字列を分けれるのであれば分けた方がいいかと思います。
ただ、僕は、varcharのカラムに数値を入れることもあるのでそこは臨機応変ですね!(電話番号や郵便番号などで「-」を入れる場合、varcharにすることもあります。(滅多にありませんが、、))

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

まず、数値と数字では明確に意味が違います。
・数値 → 算術演算に用いることが出来る値
・(アラビア)数字 → 0~9までの文字

そのカラムにで扱うものが、算術とは無縁ならそれは数値ではなく数字です。
その場合は、別途数字だけを扱う約束がある場合を除き、文字列型(VARCHAR型)を使って下さい。

そのカラムにで扱うものが、算術を行う可能性があるなら設計を一から見直す必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる