データベース設計とは?テーブルの分け方と関連付けを具体例で解説|確認問題の回答例

データベース設計とは?テーブルの分け方と関連付けを具体例で解説の確認問題の回答例です。各テーブルの1行が何を表すか、どのID同士を対応させるかに注目して確認しましょう。

問題1:現在の利用者情報を1か所にまとめる

学習記録の各行に利用者名も保存しています。利用者1001の名前を変更したところ、記録101だけ新しい名前になり、記録102は古い名前のままでした。どの情報を別のテーブルに分け、何で関連付けるとよいですか。

利用者の現在の情報をusersへ分け、id1001の行に名前を1か所だけ保存します。学習記録はstudy_logsへ入れ、user_id1001でusers.idを参照します。名前を変えるときはusersの1行を変更します。登録当時の名前を残す要件なら別の設計が必要ですが、今回は現在の名前を表示する条件です。

問題2:記録IDと所有者IDを区別する

田中さん(利用者ID1001)が学習記録を3件登録します。study_logs.idとstudy_logs.user_idには、それぞれどのような値を入れますか。例を挙げてください。

列値の例
study_logs.id101、102、104のように、study_logs内で重複しない別々のID。
study_logs.user_id3行とも1001。3件すべて同じ田中さんの記録だから。

記録103は図では佐藤さんの記録として既に使われています。空いているIDを使い、登録時の採番はDBに任せます。user_idを重複禁止にすると1人1件に制限されるため、この関係には合いません。

問題3:関係の定義とアクセス制御を分ける

列名をuser_idにすれば、存在しない利用者の記録も、他人による閲覧も防げると考えました。それぞれ、何が別に必要ですか。

存在しない利用者を拒否するには、study_logs.user_idがusers.idを参照する外部キー制約を定義し、有効にします。SQLiteでは接続ごとの有効化も確認します。所有者なしを許さないためNOT NULLも指定します。列名だけでは制約にはなりません。

他人の閲覧を防ぐには、アプリ側でログイン中の利用者を確認し、その利用者IDで取得対象を絞ります。外部キーは、現在の操作者に閲覧権限があるかまでは判断しません。登録時の所有者も、送信された任意の利用者IDではなくログイン情報から決めます。

問題4:型と必須指定だけで済ませない

学習内容にNOT NULL、学習時間にINTEGERを指定しました。空文字の学習内容や、0分の学習時間を必ず拒否できるでしょうか。このSQLiteの設計例で必要な確認を答えてください。

その指定だけでは足りません。NOT NULLが拒否するのはNULLであり、空文字や空白だけの値は別に確認します。学習内容は1〜200文字か、空白だけでないかを確認します。時間は整数かつ1〜480かを確認します。SQLiteの通常のテーブルではINTEGERという型名だけで厳密な整数限定にもならないため、DBのCHECK制約へ型と範囲の条件を定義します。

画面入力はアプリ側で確認して理由を伝え、DBにも必要なNOT NULL・CHECK制約を設定します。実際に空文字・0・481などを拒否できるか、定義と動作の両方を確かめます。

問題5:保存する値と表示文を分ける

画面には「メモはありません」と表示したいので、未入力時にその文章をDBへ保存する案が出ました。この記事の設計では、何を保存し、いつ文章を作りますか。

未入力ならNULLへそろえて保存し、一覧の表示時に「メモはありません」という文章を作ります。画面向けの案内文をメモ本文として保存しません。この方針なら案内文を変えるだけで、過去の記録を書き換えずに表示を変更できます。NULLと空文字を混在させないように、登録・取得・表示の扱いをそろえます。

元の記事に戻る

データベース設計とは?テーブルの分け方と関連付けを具体例で解説