質問をすることでしか得られない、回答やアドバイスがある。

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

ただいまの
回答率

91.27%

  • PHP

    15642questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    4556questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

チェックボックスのデーターベースの持ち方について

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 4
  • VIEW 335

annderber

score 42

お世話になります。

データーベースでのチェックボックスの持ち方についていくつか方法があるかと思います。

1.テーブルに必要項目分のフィールドを追加する
2.1フィールドにビットフラグやカンマつなぎなどで持つ
3.別テーブルとして持ち親子関係にする

正規化的に3が最もいいと思いますが、
その実装方法として考えているのが、以下のようになります

イメージ説明

全テーブルで共通のcheckboxsテーブルを1つ作成し、
各テーブルはそのテーブルからcheckboxの値を取得します。

このような設計にした場合、各画面に必要なチェックボックスを1つ1つ指定する必要があるのが1つ面倒なポイントになる気がしています。
例えば、権限設定の場合だとこの設計では

<input type="checkbox" name="permission_r" value="1">閲覧
<input type="checkbox" name="permission_w" value="1">登録
<input type="checkbox" name="permission_x" value="1">削除


になると思います。

別の方法としては

<input type="checkbox" name="permission[]" value="1">閲覧
<input type="checkbox" name="permission[]" value="2">登録
<input type="checkbox" name="permission[]" value="3">削除


として、サーバー側でハンドリングするという形です。

上記②の方法で格納すれば配列で受け取った値をカンマで繋げばよいだけですので処理は楽になりますが、変更に弱かったり検索の必要が出てくる場合は非常にまずくなりますので、③の方法がよいと考えています。

上記の設計で起きうる問題点などがあれば教えていただきたいです。

また、これは②の様なタイプの設計パターンになりますが、カンマつなぎで登録する場合、
値を1,2,3のような値で格納するか、閲覧、登録、削除と文字列で格納するか、またはr,x,xのように文字列でもアルファベットにする場合などでそれぞれどのようなメリット、デメリットがあるか教えていただきたいです。

よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

+4

チェックボックスを外部テーブル化するかどうかについては
不特定性があるかどうかが重要です
つまり、閲覧、登録、削除のように項目に規則性が高く排他性がないものについては
ユーザーテーブルの中にカラムとしてそれぞれを独立して持たせるのが有効です

逆に「趣味」や「アンケート」などユーザーや管理者側が任意に増やしていくようなものは
外部の専用テーブルにわけて、ユーザーテーブルと専用テーブル間に中間テーブルを設けるのが賢明です。
そうすることにより、専用テーブルをプログラムで走査すれば選択していないものも表示でき
任意にチェック状態を変更することが可能です。(変更するのは中間テーブル)

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/08 16:07 編集

    コメントありがとうございます。

    不特定性の多い場合は今回のような設計で対応できるということですね。
    例えば、同じuser_table内でも変更率の高いチェックボックス項目を外部テーブル、変更の少ないものはuser_tableのフィールドに含めるという感じですかね。自分としてはどちらかに統一したい気もしますが。
    また今回の設計例では画面で使用するすべてのチェックボックスを1つのテーブルで管理しようと考えていますが、このような設計は単純な項目では問題無い気がしますが、1つのチェックボックスで複数の値を持ちたい場合など、運用を続ける内に破綻するような気がするのですがいかがでしょうか。

    キャンセル

checkベストアンサー

+3

こんにちは。期待している回答ではないかもしれませんが、
私ならこうする というものをコメントします。

■ チェックボックスの場合
チェックボックスの場合は、チェックあり/なし の状態が管理できれば良いので、
boolean型がわかりやすいと思いました。
(チェックボックス用のテーブルは作成しない)

例に書かれている権限設定の場合、
「閲覧、登録 の権限は付与するけど、削除は付与しない」
「閲覧 の権限しか付与しない」
など、チェックボックスの場合は、組み合わせ管理も必要になると思いますので、
それぞれの情報をDBの項目として定義した方が管理がやりやすいと思いました。

■ラジオボタンの場合
ラジオボタンの場合は、選択肢のどれが選択されているかを識別できれば良いので、選択グループ単位で項目を定義して、選択肢の数や内容に応じて、項目属性を決定したら良いと思いました。
個人的には、DBに格納されている値から選択内容が推測できるようにした方がわかりやすい気がするので、私なら文字型でコードを定義すると思います。
この場合は、例で書かれているように選択肢の値と名称を管理するテーブルを定義して一元管理した方が作りやすいと思いました。

私なら、こんな感じでテーブル設計をすると思います。

テーブル定義
インデックス定義
レコード定義

各テーブルの中で、項目を定義して値管理をします。

このやり方のメリットとしては、
UI側は、項目ごとの値を検索してラジオボタン配置、ドロップダウンリストに追加するようにコーディングしておけば、選択可能値をレコードに追加/削除するだけで管理ができる点です。

デメリットとしては、
外部キーの定義できないと思いますので、プログラム側で値の制御が必要になります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/08 15:59 編集

    コメントありがとうございます。

    私の出した例が悪かったですね。権限系であればチェックボックスの項目は最初の要件から変わりづらいので、別テーブルにする利点があまり感じられないです。
    これがユーザーの「お気に入りジャンル」とか「趣味」など、項目の変更率が高い場合だとまた設計が変わってくるかと思います。
    ラジオボタンの設計例は大変参考になります、ありがとうございます。
    このようにチェックボックスをすべて共通で管理しようとすると、必ず例外が出てくると思います。例えば、ユーザーが会員のコースを選択した時に、コース名と紐付く「値段」があるとすると、これは別テーブルにすべきでしょうか。ただ、コースと値段は1対1で紐付いているので、同じテーブルにフィールドを追加したい気もします。このような項目毎に出てくる要件をかわしながら、綺麗なテーブル構成を維持できるか微妙な気もします。チェックボックスの項目をマスタテーブルとして管理するのは管理者ユーザーが管理しやすいようにということが多いと思いますが、普段どの程度の粒度でテーブルを分けるでしょうか。別の質問な気もしますが。

    キャンセル

  • 2018/01/08 18:02

    おっしゃる通り、要件によって設計は変わると思います。
    個人的な意見ですが、要件が変わりにくいものは、別テーブルにする必要はないと思います。(シンプルに出来るものはシンプルにした方が良いと思います)

    >例えば、ユーザーが会員のコースを選択した時に、コース名と紐付く「値段」があるとすると、これは別テーブルにすべきでしょうか。

    選択肢に補足的な情報が紐づく場合は、別テーブルでマスタ化した方が良いと思います。
    単純にコードと名称を持つだけなら、チェックボックス用の共通テーブルで管理したら良いと思います。

    (参考)私の判断基準
    ■選択肢の数、内容(名称)が変わらない
     → 関数化してハードコーディング
      (同じ項目が複数のテーブルや画面で利用する場合を考慮)

    ■選択肢の数、内容(名称)が変わる可能性がある
     (1) 選択肢は、コードと名称があれば十分
       (画像形式(bmp,gifなど)、 ファイル形式(txt,xlsx,docx など)
       → 共通テーブルで管理(機能拡張がやりやすいように)

     (2) 選択肢には補足的な情報が必要
       研修会場ID+会場名、住所、連絡先 など
       → 専用のテーブルを作成して管理

        このケースは、
        ・マスタ(住所マスタ、商品マスタなど)
        ・データ(受注情報、課題情報 など)
        も該当すると思います。
        基本的には専用テーブルを作成して、
        その上で、チェックボックスの選択肢として利用する場合は、
        処理しやすいようにテーブルのキー項目の設計を考える感じです。

    キャンセル

  • 2018/01/09 11:47

    大変参考になります。
    参考例の「■選択肢の数、内容(名称)が変わらない」というのは権限の場合で言えば、userテーブルに3権限文のフィールドを追加し、それに対応するチェックボックスの値と表示用の名称などは関数化しておく。
    権限を1つ追加する場合はuserテーブルに1フィールド追加し、プログラム側でも処理を追加する。
    この場合DBとプログラム両方の修正が必要になるが、変更が殆どないと想定されるので、そこまでのコストにはならないということですね。

    キャンセル

+3

「このような設計にした場合、各画面に必要なチェックボックスを1つ1つ指定する必要があるのが1つ面倒なポイントになる」と仰っていますが1、2、3どの手法をとったとしてもそれは同じでは?
個人的にはテーブルに「checkboxs_name」というフィールドがあるのは違和感があります。今は権限のチェックに関して例にあげられていますが、ユーザーの削除フラグや別のフラグも入れるというならばあまり良い設計とは思えません。
自分ならusersのテーブルにすべて入れると思います。その上で、フィールドを分けるかビット演算かは「複数値の組み合わせで検索し候補が増える可能性があるか」で決めます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/06 15:25

    コメントありがとうございます。

    削除フラグなどは別のフィールドとして扱う想定でいます。
    フィールド分ける場合だと、チェックボックスが追加される度に追加刷る必要が出てくるかと思います。
    またビット演算の場合、既存のチェックボックス項目の間に1つ追加して、画面表示の並びとビット演算との並びを合わせる場合、ビットの位置のずれが出てくると思います。または単純に末尾にどんどん追加していくと画面上の並びと実際のビットの位置の違いにより直感的な把握が難しくなるように感じます。
    このような問題点を踏まえた上でも別テーブルにするよりも優位性があるでしょうか。

    キャンセル

  • 2018/01/06 16:27

    直感的かどうかは個人の主観ですが私は提示のテーブル構成が直感的とは全く思えません。そもそもテーブルの構造をみてもデータの内容がわかりませんし、checkboxsテーブルをビューで開いても「usersテーブルがどのチェックを持っているのか」すらわかりません。それがわかるのはプログラムの画面を見たときです。テーブルでわからないというのは好きではないです。
    存在しないデータを追加するとき、テーブルを編集して列を増やすほうがよほど自然で直感的だと思います。インデックスも使えますしsqlが冗長にならずに済みます。

    キャンセル

  • 2018/01/06 16:32

    checkboxsテーブルを見ても「usersテーブルがどのチェックを持っているのか」は分かりませんが、
    user_table_checkboxテーブルを見ればuserテーブルのどのレコードがどのチェックボックスの値を持っているかはわかるかと思います。

    キャンセル

  • 2018/01/06 17:24

    それはselectして見ればということですよね?構造を知るためにselectまでしないとわからないので結局は直感的ではないと感じます。それにuser_table_checkboxみればわかるということはcheckboxsテーブルに行を追加した時にuser_table_checkboxにuser_table分追加するということですよね?逆にuser_tableに追加した時もuser_table_checkboxに追加するんですね?トリガーを仕込むにせよ手間だと思います。

    キャンセル

  • 2018/01/06 17:52

    「構造を知るためにselectまでしないとわからないので結局は直感的ではないと感じます。」とおっしゃている構造とは何を指しているのでしょうか、テーブル設計についてでしょうか。どのユーザーがどのチェックボックスを持っているかということに関して言えばどちらにしろselectが必要になるかと思います。
    またここでおっしゃっていることは1対多の関係になるテーブル設計すべてに言えるとおもいますが、テーブルを分割すること事態が駄目だと言うことでしょうか。

    「user_table_checkboxみればわかるということはcheckboxsテーブルに行を追加した時にuser_table_checkboxにuser_table分追加するということですよね?」
    上記の意味が分かりかねます。私の説明が足りなかったのかもしれないですが、例えばクライアントがユーザー登録時にチェックボックスにチェックを入れたらuser_table_checkboxにレコードが追加される想定なので、checkboxsに追加=user_table_checkboxに追加するとはなりません。

    「user_tableに追加した時もuser_table_checkboxに追加するんですね?」
    ユーザー新規登録時にチェックボックスが入っていれば当然user_table_checkboxにレコードを追加します。
    別にトリガーを使う必要はありません。

    キャンセル

  • 2018/01/06 18:33

    「チェックボックスにチェックを入れたらuser_table_checkboxにレコードが追加される想定」ならselectで見てもどのチェックがあるかはわからないのでは?全件持っているユーザーを知っていないと判断できませんよ。
    構造というのは「閲覧」「登録」「削除」というデータです。フィールドで追加すれば「閲覧」「登録」「削除」というフィールドがuser_tableにあるのでテーブルのデザインを見ればわかります。annderber氏のデザインでは「閲覧」「登録」「削除」というのはuser_table_checkbox.checkbox_nameやcheckboxs.nameなどの「値」になっています。

    キャンセル

  • 2018/01/08 15:23 編集

    おっしゃっているのはcheckboxsテーブルのレコードのどれがuser_tableで使用されるチェックボックスなのか分からないと言うことでしょうか?
    それであればcheckboxsテーブルにtable_nameフィールドを追加して対応すればどうでしょうか。または、全テーブル共通ではなく、使用するテーブル毎または画面毎に分割します。

    キャンセル

  • 2018/01/08 21:13

    最初の件はそれであっています。checkboxsテーブルにtable_nameフィールドを設けないといけない時点で直感的でないと自分なら感じます。別にこうしろと言っているつもりはないので、それでいいと思えるならそれでもいいと思います。意見を求められていたので私ならこうすると思うというのを言っているだけです。その実装と私の実装で可能不可能の差はほとんどないと思います。

    キャンセル

+2

こんにちは。
 

上記の設計で起きうる問題点

とのことですが、拝読して疑問に思ったのが、

後々、入力のUIが変わったり、別のUIからの入力にも
対応しなければならなくなった場合、どうやって対応するのか?

ということです。

たとえば、例として挙げられている、

<input type="checkbox" name="permission_r" value="1">閲覧
<input type="checkbox" name="permission_w" value="1">登録
<input type="checkbox" name="permission_x" value="1">削除

は 初期リリースのPC画面用に作ったものとしますと、
将来、画面デザインのリニューアルや、もしくは別の
デバイス(iPadなど)用の登録画面を作ることになって、
そこでは複数選択の <select> になったと仮定すると、
その場合はどうなるのでしょうか?

おそらくUI側は

<select name="permission" multiple>
    <option value="r">閲覧
    <option value="w">登録
    <option value="x">削除
</select>

のようになると想定していますが、このとき DBふくむバックエンド側は
どういう対応をするのでしょうか?

  • select から入力されたものでも、xxxx_checkbox テーブルを参照する。

または、

  • 新たに、xxxx_select あるいは、xxxx_optionのようなテーブルを新規に追加する。

といった対応をするのでしょうか?

疑問に思ったことは以上です。
参考になれば幸いです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/01/06 15:18

    コメントありがとうございます。

    上記の場合ではcheckboxテーブルからその項目を削除し、別のマスタテーブルを作成するようにするかと思います。jun68yktさんはどのような設計をするでしょうか。例えばチェックボックス項目の変更が多く、かつその項目で検索をかける必要がある場合です

    キャンセル

  • 2018/01/06 15:45

    > 上記の場合ではcheckboxテーブルからその項目を削除し、別のマスタテーブルを作成するようにするかと思います。

    なるほどです。
    入力する UI の変更、追加によって、当該 UI 用のテーブルの変更、追加作業が
    発生することは、annderberさんにとっては想定内ということであれば、
    私の疑問は杞憂でした。

    > jun68yktさんはどのような設計をするでしょうか。

    私なら、UIの変更によってマスタテーブルの変更、追加作業が
    発生しないで済むようなテーブル設計を考えると思います。

    キャンセル

  • 2018/01/06 15:57

    そもそもチェックボックス用のマスタテーブルを用意すること自体問題であるという感じでしょうか。
    もう少し具体的な設計方法をご教授いただけるとありがたいです。

    キャンセル

  • 2018/01/08 19:55

    こんにちは。

    以下、2点について、それぞれ回答します。

    (1) > そもそもチェックボックス用のマスタテーブルを用意すること自体問題であるという感じでしょうか。
    (2) > もう少し具体的な設計方法をご教授いただけるとありがたいです。


    (1) > そもそもチェックボックス用のマスタテーブルを用意すること自体問題であるという感じでしょうか。

    >問題
    とまでは断言できないです。
    というのは、私が回答に書いたような、別のUIから入力する状況になったときに、

    > 上記の場合ではcheckboxテーブルからその項目を削除し、別のマスタテーブルを作成するようにするかと思います。

    というお答えだったので、別のUI になったときの対応をするのは想定内という
    ことのようですので、それであれば、問題ないのではないか?と考えています。

    ただ、もし、このシステムの開発が、WEBデザイナーふくむフロントエンド担当チームと、
    DB設計やビジネスロジックを設計、実装するバックエンド担当チームとで
    分かれている体制であると仮定すると、
    UIふくむフロントの仕様がなかなか決まらなかったりする中で、
    バックエンド側も並行で設計、実装を進めていかないといけない
    状況が発生しがちで、(実際、そういう状況は何度も経験しましたが。)
    UIの名前(ここでは checkbox )をテーブルの物理名の中に含めて
    user_table_checkbox のようなものを作るのは、
    後々、デザインやフロントエンドの都合で当該のUIが変更になったときに、
    物理名がuser_table_checkboxありきで走っていた
    バックエンド側に与えるインパクトが大きいのではないか、
    という懸念があります。

    ただし、上記の懸念は、ご質問の対象システムを、annderber 様が
    お一人で設計して開発するのであれば、これもまた、何ら問題に
    ならないことです。


    (2) > もう少し具体的な設計方法をご教授いただけるとありがたいです。

    私は、枯れたデザインパターン、つまり使い古されてよく知られた手法や
    設計哲学を探してきて、それを適用して楽することを考える傾向が
    ありますので、ユーザー権限については、具体的にはロールベース
    アクセス制御(RBAC)という設計パターンを踏襲すると思います。

    wikipediaにもあります。
    https://ja.wikipedia.org/wiki/ロールベースアクセス制御

    ER図は以下のようなものです。
    http://www.darwinbiler.com/role-based-access-control-erd/

    業務システムにおけるロールベースアクセス制御
    https://qiita.com/kawasima/items/8dd7eda743f2fdcad78e

    RBACのような、よく知られたパターンを使って設計しておけば、
    メリットとして、実装時に何か問題や壁につきあたって
    質問サイトに投げる際にも、
    「ユーザー権限周りを、RBACに準じて作っているのですが・・・」
    と言えば、それは
    「WEBサイトを Ruby on Rails で作っているのですが・・・」
    と言うのと同じで、知っている人が多い分だけ有益な助言を
    もらいやすくなると期待できます。

    とはいえ、教科書に出ていることに沿って作らなければならないという規則は
    ないので、annderber 様が、これでOKと確信できる設計で進めるのが
    ベストなのではないでしょうか。なんだか玉虫色の答弁になってしまいましたが、
    以上を私の回答とさせて頂ます。

    キャンセル

  • 2018/01/09 10:01

    ありがとうございます。参考にさせていただきます。

    キャンセル

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

ただいまの回答率

91.27%

関連した質問

同じタグがついた質問を見る

  • PHP

    15642questions

    PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

  • MySQL

    4556questions

    MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。