練習問題の答えと理由
Practice Questions: Answers and Notes
本の各章の最後にある「答えと理由」と同じ内容です。
第1章:データを使う仕事とデータベース
自己チェック
1節
- AはIT、Bは情報、Cは未記入です。
- 後の時刻の値が正しいとは限らず、変更理由などを確かめる必要があるからです。
- 基準の情報と変更手順を明確にできるからです。
2節
- 計算、並べ替え、グラフ作成などです。
- 共有機能を持つ製品があります。
- 利用者、更新、制約、検索、アクセス管理、運用などです。
3節
- 表の定義、検索、追加・更新・削除、設定に応じたアクセス制御などです。
- 一つの履修登録です。
- 履修表の二行で、学生ID S02に結びついています。
4節
- 同時更新の有無、重複防止、必要な出力などです。
- 必ずとは言えません。同じ人数でも更新方法や制約が異なるからです。
- 必要な一覧が出るか、誤ったIDを防げるか、担当者が操作できるかを試します。
確認問題
Q1 正答はBです。利用者、更新方法、重複を防ぐ条件を確かめ、必要に合う方式を比べます。Aは複数の正本を残すため、食い違いが続きます。Cは共有機能があっても、重複を防ぐ条件を確認せず方式を決めています。DはID順の一覧だけで方式を決め、更新や制約を比べていません。
Q2 正答はDです。DBMSはデータベースの構造やデータを定義・操作・制御するソフトウェアです。Aは役割を並べ替えだけに限定しています。Bは全利用者にすべてのデータを公開するとしていますが、そのような公開はDBMSの定義ではありません。CはDBMSの役割を共有とアクセス権だけに限り、構造やデータの定義・操作を含めていません。
練習
練習1の正答はBです。小さな表の計算やグラフ作成には表計算が使いやすい場合があります。Aは関係データベースが表でデータを扱うことを否定しているため誤りです。Cは一人なら制約が不要と決めつけています。Dは共有機能があってもID重複を防ぐ条件が不要とは限りません。
練習2の例:表計算は小規模な集計やグラフ作成、DBMSは複数担当の制約付き台帳などが候補です。理由を二つずつ要件と結びつけます。
練習3の例:構造・制約の定義、検索や更新の管理などから二つ説明できればよいでしょう。
練習4は、方式を二つの要件に結び付けていればよいでしょう。
考えよう
学生IDで対象を確かめ、更新時刻と担当者を見ます。その後、担当者に変更理由を確認し、基準となる情報を決めます。学生IDだけ、または時刻だけで正しい値が必ず決まるわけではありません。
同じ行を同時に直す可能性、重複を防ぐ方法、変更履歴の必要、更新できる人を確認します。二つ挙げて、なぜ必要かを説明できればよいです。
グループで話そう
一つだけの正解はありません。利用者・更新・制約・出力・運用の条件を挙げ、その条件と選んだ候補の関係を説明できるかを確かめます。
第2章:表・行・列・キー
自己チェック
1節
- 学生一人を表します。
- 学生一人の授業登録一つを表します。
- 同じ表の行を同じ基準で読み、各行に必要な列やキーを選びやすくなります。
2節
name列です。- 所属です。
- student_idは文字として、creditsは整数として扱います。
3節
- 表の各行を一意に識別するために使います。
- student_idはstudents、course_idはcoursesを参照します。
- student_idとcourse_idの組の重複を防ぐ条件です。
4節
- 値が存在しない、または分からないことです。
- 数値のゼロです。
- NULLは未採点を示すため、0点と区別する必要があります。
確認問題
Q1 正答はDです。未採点にはNULL、採点した結果が0点なら数値の0を使います。Aは二つを同じ値にするため区別できません。Bは文字列の空文字を数値列に使い、点数の意味を表しません。Cは未採点と0点を反対にしています。
Q2 正答はBです。Aでは同じ学生の複数授業を別々に識別しにくくなります。Cは名前や授業名が重なる場合や変更時に関係を追いにくくします。Dには授業を示すIDがなく、どの授業への登録かが分かりません。
練習
- studentsは学生一人、coursesは授業一つ、enrollmentsは学生一人の授業登録一つです。一行の意味を決めると、表ごとに何を記録するかが定まり、同じ学生が複数の授業を取ることも履修表の複数行で表せます。
- 主キーはstudents.student_id、外部キーはenrollments.student_idです。IDで同名の学生を区別し、履修表から学生表を参照できます。履修表にはcoursesを参照するcourse_idも置きます。
- NULLを未採点、0を0点、空文字を空のメモに対応させます。NULLは値がない、または分からないことを示し、0は数値、空文字は文字列です。
考えよう・グループで話そう
考えよう1の例:学生表と履修表の両方に所属を保存すると、変更後に片方だけ直して値が食い違う可能性があります。学生表に所属を置き、履修表からIDで参照します。
考えよう2の例:enrollment_idは登録ID、student_idとcourse_idは学生・授業のIDです。
グループで話そうに一つの正解はありません。一行の意味、キー、NULLを許す列を例と結びつけて説明できるかを確かめます。
ワークシート
studentsは一行が一人、主キーはstudent_id、外部キーはありません。programのNULLは要件で判断します。enrollmentsは一行が一登録です。主キーはenrollment_id、外部キーはstudent_idとcourse_idです。scoreは採点前にNULLを許し、0点と区別します。
第3章:SELECTで取り出す
自己チェック
1節
student_id, nameです。- 学生表から取り出す指定です。
student_idです。同名の行をID順にできます。
2節
- WHEREです。
- SQLに
?を書き、値を別の引数で渡します。 nameは名前の列で、所属はprogramだからです。
3節
course_idを加えます。- 返す行数です。
- ORDER BYです。LIMITは行数を制限します。
4節
- 列は
student_id, name、表はstudentsです。 program = ?にし、値ITを別に渡します。- 列名、値、順序、行数を比べます。
確認問題
Q1 正答はAです。SELECTで列を選び、ORDER BYで順を指定します。Bは全列を含み、Cは所属を出します。Dは名前が先の並べ方で、ID順という依頼に合いません。
Q2 正答はCです。WHEREでITを選び、ORDER BYで名前、次にIDの順にします。Aはname列を調べます。BはITの条件がなく、5人から先頭4人だけを返します。DはID順が先で、5人から4人だけを返します。
練習
- 列名はstudent_id,name。行はS02・ラジャン、S04・教材用の学生の順です。
SELECT course_id, title FROM courses ORDER BY course_id;です。C01・データベース基礎、C02・表計算演習、C03・情報倫理の順です。- ORDER BYです。WHEREは条件に合う行を選びますが、並び方を指定しません。
考えよう・グループで話そう
考えよう1は、IDも表示すると同じ名前の行を区別しやすくなります。必要な列は使う目的に合わせます。
考えよう2は、先頭2行でも順序を示すならORDER BYを使います。上位2件ならcreditsの降順と同順位の副順序を指定してからLIMIT 2にします。
グループで話そうは、列・条件・順・件数を分け、ORDER BYを先に決める理由と値を別に渡す理由を説明できればよいでしょう。
ワークシート
空欄付き練習は値("国際ビジネス",)でS01の1行です。自力課題はcredits=1を選び、C02・表計算演習とC03・情報倫理をID順に出します。列・条件・値・順を確かめます。
第4章:集計
自己チェック
1節
- 表の行数です。
- score列に値が入っている行の数です。NULLの行は数えません。
- 合計は251、平均は約83.67です。平均は251÷3で求めます。
2節
- いいえ。NULLはこの例では未採点です。
- scoreに値がある行が3行だからです。NULLは平均の対象になりません。
- 採点数です。平均の対象件数が分かります。
3節
- course_idの値が同じ行を一つのグループにまとめます。
- 登録数は1、採点数は0です。
- C03に点数がなく、平均を計算できないためです。
4節
- グループ化の前です。
- HAVINGです。
- ORDER BYです。
確認問題
Q1 正答はAです。COUNT(*)は履修4行、COUNT(score)は採点3件、合計は251です。BはNULLを採点数に加え、Cは平均の分母を4としており、Dは履修行を3行と数えています。
Q2 正答はCです。GROUP BYは行を授業ごとにまとめ、HAVINGは集計後に条件を満たすグループを選びます。登録数2件以上はC01だけです。Aは集計後の件数条件をWHEREに置いています。BのHAVINGは並び順ではなく抽出条件です。DのLIMITは返す行数の上限で、登録件数の条件ではありません。
練習
COUNT(*)は4、COUNT(score)は3、SUM(score)は251です。AVG(score)は83.66666666666667(約83.67)です。COUNT(*)は全行を数えます。ほかはscoreの値を対象にします。- C01は登録2・採点2・平均86.5、C02は登録1・採点1・平均78.0、C03は登録1・採点0・平均NULLです。C03には点数がないため、0点や0という平均とはしません。
- 次のSQLです。結果はcourse_id,n列のC01,2です。
SELECT course_id, COUNT(*) AS n
FROM enrollments
GROUP BY course_id
HAVING COUNT(*) >= 2
ORDER BY course_id;考えよう・グループで話そう
- 「点数は4件」は誤りです。4は履修表の行数で、scoreに値がある件数は3です。NULLの行を0点として平均の分母に加えることもできません。平均は251÷3で約83.67と報告します。
- 採点数も示すと、平均の対象件数を確認できます。
グループの項目を二つ選び、必要な理由を説明できればよいでしょう。例:「平均と採点数が必要です。平均だけでは対象件数が分からないからです。」
ワークシート
C03は登録1・採点0・合計NULL・平均NULLです。C01は登録2・採点2・平均86.5です。登録数と採点数を区別できれば完成です。
第5章:JOINで表を結ぶ
自己チェック
1節
- 学生IDと授業IDです。履修表がそれぞれのIDを持ち、学生表・授業表の対応する行へつなぎます。
- どの列の値が一致すると行を結ぶかを指定します。
- 左の
e.student_idは履修表、右のs.student_idは学生表の列です。短い表名で区別しています。
2節
- 未履修の学生には結合条件に合う履修行がないためです。INNER JOINは一致した組合せを残します。
- ラジャンにはE02とE03の二つの履修登録があります。授業ごとに別の行となります。
- E04の点数は未採点です。NULLは0点を表していません。
3節
- 右側の対応行がない列をNULLで補った行になります。
- ONです。学生を左側に保ち、C01の登録だけを右側から結びます。
- WHEREのC01条件を満たす右側の値がNULL補完行にはありません。そのため、該当する学生行は結果に残りません。
4節
COUNT(e.enrollment_id)で右側の履修IDを数えます。対応する登録がない学生は0件です。- 1です。LEFT JOIN後に作られたNULL補完行をCOUNT(*)が数えます。
- E02とE03の二つの履修IDを数えたためです。
確認問題
Q1 正答はAです。studentsを左側にしてLEFT JOINを使うと、履修がない学生もNULL補完行として残ります。BはINNER JOINを未履修行も補う結合として説明していますが、一致行だけを残します。Cは履修表だけから未履修者を作れません。Dの説明はWHERE条件の働きと逆です。右表の条件をWHEREに置くと、NULL補完行はその条件に合わず、未履修者は残りません。
Q2 正答はDです。COUNT(enrollment_id)は、履修IDのNULLではない値を数えます。履修がなければNULL補完行のIDは数えられず、0件です。AのCOUNT(enrollment_id)はNULLの履修IDを数えないため、未履修者は0件です。COUNT(*)なら補完行を1行と数えます。Cは左側のstudent_idを数えるため、未履修者の左側IDも数えて1件になります。Bは学生IDの合計では履修件数を求められません。
練習
- INNER JOINではS03とS04は出ません。対応する履修行がないからです。LEFT JOINでは両方が出て、履修IDがNULLになります。左側の学生行を残すためです。
- 次のSQLを実行します。
SELECT s.student_id, s.name,
COUNT(e.enrollment_id) AS enrollment_count
FROM students AS s
LEFT JOIN enrollments AS e
ON e.student_id = s.student_id
GROUP BY s.student_id, s.name
ORDER BY s.student_id;列はstudent_id, name, enrollment_countです。順にS01が2、S02が2、S03が0、S04が0です。右側のIDにNULLがある行は数えないため、未履修者が0件になります。
- ONに条件を置くと4人が残り、S01とS02にC01の登録が結び付きます。S03とS04はNULL補完行です。WHEREに同じ条件を置くと、S01とS02だけが残ります。WHEREは結合後の行を条件で選ぶため、C01に一致しないNULL補完行も除かれます。
考えよう
- 未履修の学生も連絡対象なら、結果から除くと連絡漏れにつながる可能性があります。studentsを左側に置くLEFT JOINにして全員を残し、履修情報がないことはNULLとして読み取ります。
- COUNT(*)はLEFT JOIN後の補完行も数えるので、未履修者は1と表示されます。COUNT(e.enrollment_id)は値のある登録IDだけを数えるので0になります。登録数の意味には後者が合います。
グループで話そう
一つの正解はありません。左側に残す対象、結びたい表、共通するID、未対応時の表示を説明できているかを確認します。全員を残す依頼にはLEFT JOIN、一致した組合せだけでよい場合はINNER JOINを使う案が考えられます。
ワークシート
- 左側はstudents、右側はenrollmentsです。
- 結ぶ条件は
e.student_id = s.student_idです。 - WS5-1のC01一覧では、C01の履修だけを結ぶ条件をONに加えます。出力はS01/E01、S02/E02、S03/NULL、S04/NULLです。
- 練習2から参照する全授業の件数は
COUNT(e.enrollment_id)で数え、4人の件数は2、2、0、0です。 - C01だけの件数を集計する場合は1、1、0、0です。
説明とSQLの両方で、未履修の学生を残すことと、登録IDを数えることが確認できれば完成です。
第6章:データを追加・更新・削除する
自己チェック
1節
- 表に行を追加します。
- 列リストとVALUESを同じ順にします。
- IDを条件にSELECTし、行数と値を確認します。
2節
- 対象ID・変更前の値・件数が予定どおりか確かめます。
- WHEREにstudent_id=S02の条件を書きます。
- 変更件数と、対象の値が期待どおりか確認します。
3節
- 削除するID・値・対象件数をSELECTで読みます。
- WHEREがなければ表の全行が対象です。
- 参照元の履修行と、削除してよい範囲を調べます。
4節
- トランザクション内の変更を確定します。
- 件数や値が想定と違い、変更を残さないときです。
- 確定を止め、条件を見直し、必要ならROLLBACKします。
確認問題
Q1 正答はAです。INSERTは列リストとVALUESで行を加えます。BはWHEREの誤用、Cは既存行の更新、Dは削除です。
Q2 正答はBです。WHEREでS02を限定し、前後をSELECTします。Aは全4行を変更します。CはprogramがITの全員を対象にするため、S02だけという指定より範囲が広くなります。DはINSERTとUPDATEの混同です。
練習
対象は1行です。前後に次のSELECTを実行します。
SELECT student_id, program FROM students WHERE student_id='S02';更新SQLは次のとおりです。
UPDATE students SET program='情報' WHERE student_id='S02';所属がITから情報へ変われば正答です。
次のSQLを実行し、同じIDでSELECTします。
INSERT INTO students(student_id, name, program) VALUES ('S05', '教材用の学生', 'IT');S05・教材用の学生・ITの1行が結果です。
確定を保留し、WHEREと事前SELECTを見直します。確定前ならROLLBACKし、件数を確認してからやり直します。
考えよう
- WHERE・対象ID・件数を調べ、確定前ならROLLBACKします。原因と取消方法を挙げます。
- 参照する表と行、削除後に必要な情報が残るか確かめます。
グループで話そう
SELECTで対象や値を事前に読むと、条件違いやIDの取り違えを見つけられます。理由も述べていれば正答です。
ワークシート
ワークシート
空欄練習は、削除前にS05の3列を読み、1行と確認します。削除後は0行で、履修表に参照されないことも確かめます。自力課題はS03の所属が観光と確認してから、S03だけを観光情報へ変更し、事後の値・件数・他の行を照合します。
第7章:CREATE TABLEと制約
自己チェック
1節
- データベースに表を作ります。
- TEXTです。IDや名前は文字列だからです。
- データ型と制約を書きます。
2節
- NULLです。空文字や空白だけの文字列とは異なります。
- 列または列の組で値が重なる登録を防ぎます。
- いいえ。空文字はNULLではなく、NOT NULLだけでは拒否されないためです。
3節
- 表の各行を一意に識別します。
- 学生表のstudent_idと、授業表のcourse_idを参照します。
- 同じ学生IDと授業IDの組合せを二度登録することを防ぎます。
4節
- 受け入れる値と拒否する値です。
- 空文字をどう扱うか決め、CHECKや入力時の検査などを考えます。加えた条件も試します。
- そのSQLite接続で外部キー制約が有効であることを確認できます。
確認問題
Q1 正答はCです。Cはcourse_idをNULL不可の主キー、titleをNULL不可・重複不可にします。AはIDを一意にしますが、主キーとして指定していません。BはUNIQUE(course_id,title)でtitle単独の重複を防げません。DはTEXT主キーのNULL不可を明記していません。
AはIDを一意にしますが、主キーとして指定していません。BのUNIQUE(course_id,title)はtitle単独の重複を防げません。DはTEXT主キーのNULL不可を明記していません。
Q2 正答はCです。NOT NULLはNULLを、UNIQUEは重複を拒否します。空文字はNULLではないため、許される場合があります。
AはUNIQUEの役割を逆にします。Bは空文字まで拒否すると誤解しています。Dのような自動変換はありません。
練習
enrollment_idは主キー、student_idとcourse_idは外部キーです。UNIQUE(student_id, course_id)で組合せの重複を防ぎます。- NOT NULLはNULLを、UNIQUEは重複を拒否します。SQLiteでは
title=''は受理されます。 - 空文字を拒否する要件か決め、CHECKなどを加えます。空文字の拒否と通常名の受け入れを試します。
考えよう・グループで話そう
授業名を必須・重複不可にする理由と、NULL・空文字・空白の扱いを説明できればよいでしょう。
ワークシート
titleはTEXT、NULL不可、重複不可、UNIQUEです。NULLと重複名は拒否され、空文字はNOT NULLだけでは拒否されません。
第8章:ER図と正規化
自己チェック
1節
- 一人の学生が一つの授業に登録したことです。
- 学生と授業の組合せごとに行を作り、点数を記録できます。
- 前者は0件以上、後者は一件です。
2節
- 同じ学生IDには一つの名前が対応する関係です。
- 決まりません。学生IDと授業IDの組で決まります。
- teacher_idから決まります。
3節
- 各列に一つの値を置き、授業ごとに行を作ります。
- student_idだけで決まる名前を、履修行へ繰り返さないためです。
- teacher_idで名前が決まるためです。授業表の一部だけを直す危険を減らせます。
4節
- 各表のIDを使います。
- student_id、course_id、scoreを残します。
- IDで結んだ三行を元と比べます。
確認問題
Q1 正答はDです。第1正規形では一列に一つの値を置き、繰返し列を使いません。Aは繰返し列を増やします。Bは一つのセルに複数の授業名を入れるため、一セル一値になりません。Cも授業ごとの繰返し列を残します。
Q2 正答はDです。nameはstudent_idだけで決まるため、学生表へ分けます。scoreはキー全体で決まります。Aは学生名を履修行ごとに繰り返し保存し、一部キーだけで決まる列を残します。Bはstudent_idをキーにすると、同じ学生の複数授業の行を区別できません。Cはscoreがキー全体で決まる条件を取り違えています。
練習
- 授業ごとに行を作ります。一行は学生一人の授業一件への登録です。
- scoreはキー全体、nameはstudent_id、titleはcourse_idだけで決まります。
- teacher_idから教員名が決まるため、teachers表に分けると改名は一か所で済みます。
考えよう・グループで話そう
- 学生ID・授業ID・教員IDで表を結び、必要な列が揃うか確かめます。
- 担当変更の手順や、同じIDに複数の名前を付けない規則を確認します。
- 一行の意味・キー・接続列を図にし、分割前の三行が戻るか確かめます。
ワークシート
空欄は「teacher_idで決まる」です。teacher_idから教員名が決まります。一部だけ直すと同じ教員IDに異なる名前が残ります。teachers表へ分け、courses.teacher_id = teachers.teacher_idで授業と教員を結びます。履修表はenrollments.course_id = courses.course_idで授業と結びます。
第9章:トランザクションと同時利用
自己チェック
1節
- トランザクションです。
- C01総登録2行、残席2です。
- ROLLBACKを実行します。
2節
- 処理全体を実行するか、全体を取り消す考え方です。
- 一つです。
- 原子性・一貫性・独立性・永続性です。
3節
- データの複製を別に保存し、必要時に戻せるようにすることです。
- いいえ。元データを上書きしない場所で試します。
- 表、ID、件数、値、外部キーの関係です。
4節
- 対象・ID・開始終了値・件数・終了命令です。
- 今回分0行、総登録2行です。
- いいえ。まず値と確定状態を確認します。
確認問題
Q1 正答はAです。二つの変更を同じまとまりにして、条件不成立ならROLLBACKします。Bは両方を先に確定し、条件不成立でも後から一方だけを削除します。Cはバックアップを取消命令と同じように扱っています。Dは履修追加を確定してから残席を更新するため、残席更新に失敗すると履修だけが残るおそれがあります。
成功例はBEGIN後に履修と残席を変更してCOMMITします。失敗例は別DBで仮変更後にROLLBACKします。今回分の0行とC01総数2行を区別します。
Q2 正答はCです。SQLiteの書込みトランザクションは同時に一つです。復元後は表や件数などを照合します。AはSQLiteで複数の書込みが同時に確定するという点と、復元後に件数だけを見る点が誤りです。Bは復元後の照合を省いています。DはSQLiteの書込みが一つずつである点を取り違えています。
SQLiteでは書込みトランザクションは同時に一つです。バックアップは復元後に表、ID、件数、主要値を照合します。ここでいう同時書込みの説明はSQLiteに限ります。
練習
- 開始は総数2行・残席2です。BEGIN後に履修行と残席を更新します。成功はCOMMIT後、今回分1・総数3・残席1。失敗はROLLBACK後、今回分0・総数2・残席2です。
- 原子性・一貫性・独立性・永続性です。全体の取消、制約、途中状態、確定後の保存に順に対応します。
- 表名、ID、件数、残席、外部キーなどです。三項目以上と理由があれば正答です。
考えよう・グループで話そう
- 画面や集計が実態と合わなくなります。履修行・総数・残席を照合できれば正答です。
- 製品の読書き・競合時の扱いとアプリ側の再確認方法を調べます。SQLiteの説明を広げなければ正答です。
- 元DBを上書きしない場所に復元し、表・ID・件数・値を照合します。適切な別案も認めます。
ワークシート
空欄の正答は、失敗例の「ROLLBACK」「今回分0行」「C01総登録2行」「残席2」です。開始時と同じ総登録数・残席へ戻り、E06が今回分として残っていないと確かめられれば完成です。
第10章:安全に使い、設計を説明する
自己チェック
1節
- 集めず、表示しません。
- 本人だけとなる条件を決めます。
- 件数・ID・参照関係を見ます。
2節
- 目的に合わせて分けます。
- 件数・ID・参照関係を見ます。
- 組織窓口や公式情報で確認します。
3節
- 外部から受け取った値を不適切にSQLへ組み込み、意図しないSQLとして解釈されるおそれがある問題です。対策としてSQL文と値を分けます。
- 値がSQLとして解釈されるおそれがあります。
- 攻撃文字列や手順は扱いません。
4節
- SQLに
?を置き、値を別引数で渡します。 - いいえ。SQLiteにGRANT/REVOKEはありません。
- DBMS、アプリ、OSの機能から決めます。
確認問題
Q1 正答はBです。教員は担当授業、学生は本人の履修だけを参照し、目的に必要な列を使います。Aは教員の参照範囲が広すぎます。Cは成績一覧に不要な住所・個人メールも表示します。Dは教員に担当外の成績の行まで削除できる範囲を与え、必要な権限を超えています。
Q2 正答はBです。?と別引数を使います。Aは値をSQL文に連結し、Cは値を列名と混同します。DはSQLiteにないGRANTを使います。
練習
- 教員は担当授業の氏名・授業名・点数を参照し、必要なら更新します。学生は本人の履修を見て、成績を変更しません。運用担当者は複製を管理します。
- 表の件数、学生・授業ID、参照関係を照合します。不足や重複、IDの不一致を確認します。
- 例:
cur.execute("SELECT student_id,name FROM students WHERE program=? ORDER BY student_id", (program,))。SQL文は第一引数、値はタプルの第二引数です。結果はstudent_idとnameの二列です。
考えよう・グループで話そう
目的・列・役割・保管先・復元確認が結びついていればよいでしょう。個別条件は組織窓口や公式情報で確かめます。
ワークシート
学生には本人の履修、教員には担当授業の点数を見せます。不要列を外し、複製後に件数等を照合します。値は別引数にします。