応用情報技術者 2018年 秋期 午後 問06
入室管理システムの設計に関する次の記述を読んで、設問1~5に答えよ。
H社は中堅の食品会社で、社内システムのデータベースの統合を検討している。現在、社内システムごとにデータベースのサーバを用意して運用しているが、関係データベース管理システム(以下、RDBMSという)のライセンスコストと運用コストを削減するために1台のサーバに統合し、各社内システムのデータベースは、統合したサーバのRDBMSでスキーマを分けて管理することになった。
〔社員情報の共用〕
全ての社内システムは、社員IDや氏名などの社員情報を使用する。現在は、人事システムが管理している社員情報のマスタデータを月次処理で各社内システムに配布して運用しているが、最新の情報が反映されるのが翌月になること、月次処理の運用負荷が大きいことなどから改善が望まれている。今回、サーバを統合するに当たり、各社内システムにデータを配布するのではなく、人事システムが管理する社員情報に関連する実表を参照する方式に変更することを検討している。人事システムの社員情報に関連する実表を表1に示す。

セキュリティの観点から検討した結果、人事システム以外の社内システムから社員情報に関連する実表を直接参照するのではなく、社員情報を使用する社内システムごとに必要な列だけをビュー表として公開し、ビュー表を参照する方式を採用することに決定した。
〔入室管理システム〕
会社内の特別な部屋の入退室管理を行う入室管理システムは、サーバ統合の対象となるシステムの一つである。入室管理システムで利用する主な実表とビュー表を表2に、E-R図を図1に、入室に関する主なユースケースを表3に示す。

表3のユースケース“入室”で、入室可否をチェックし、否の場合は0を、可の場合は1以上を返すSQL文を図2に示す。ここで、“:社員ID”は指定された社員IDを格納する埋込み変数、“:室ID”は指定された室IDを格納する埋込み変数、“:今日”はSQL文実行時の現在日付を格納する埋込み変数である。また、ROOMは入室管理システムのスキーマ名で、表は“スキーマ名.表名”で表記する。
〔各社内システムのRDBMSユーザ〕
社内システムごとにデータベース管理者(以下、DBAという)が存在する。DBAは表の所有者であり、他のユーザに対して、自分が所有する表へのアクセス権限を付与することができる。DBAは、各社内システムのアプリケーションプログラム(以下、APという)が表のデータにアクセスすることができるようにAP用のユーザに対して、適切な権限を付与する。各社内システムのスキーマ名と、DBA用、AP用のRDBMSユーザ名を表4に示す。

〔RDBMSの表のアクセス権限に関する主な仕様〕
使用しているRDBMSの表のアクセス権限に関する主な仕様を(1)、(2)に示す。
(1) 表のデータに対して、所有者以外のユーザが参照、挿入、更新及び削除を行うためには、表に対して対応するアクセス権限(SELECT, INSERT, UPDATE及びDELETEの各権限)を所有者から付与してもらう必要がある。
(2) ビュー表にアクセスする場合、そのビュー表が参照する表のアクセス権限は不要である。
〔入室管理システム用の社員ビュー表〕
表2のビュー表“入室管理用社員”を定義するSQL文を図3に示す。

このビュー表を入室管理システムのAPが参照だけできるように権限を付与するSQL文を図4に示す。
〔入室申請時の確認の強化〕
管理者は、“申請者が入室希望社員の組織長であること”を確認することになった。
そのため、ビュー表“入室管理用社員”に組織長の氏名が必要となり、図5に示すSQL文に変更した。
設問1:
問題文を見る図1に適切なエンティティ間の関連を記入し、E-R図を完成させよ。図1の凡例に倣うこと。
模範解答
(図を参照)


解説
解答の論理構成
- エンティティの構成を確認
- 【問題文】では「入室管理用社員」「室」「入室許可」「入退室ログ」の4エンティティが図1に配置済みです。
- 外部キーの所在で親子関係を判断
- 表2に示された「入室許可」には “社員ID” と “室ID” が含まれ、両方とも主キーではありません。これは「入室管理用社員」「室」を参照する外部キーであることを示唆します。
- 同様に「入退室ログ」にも “社員ID” と “室ID” が掲載されており、登録される都度、どの社員がどの室に入退室したかを記録する明細行であると読み取れます。
- ユースケースで関係を裏づけ
- 表3のユースケース“入室”は「“社員ID” が “室ID” について入室可否をチェック」すると記載されています。入室可否判定は「入室許可」から情報を取得するため、社員と室の両方に対して多対1の従属関係を持つことが分かります。
- 関連(リレーション)の方向を決定
- 親(1側):主キーを持ち、他から参照されるエンティティ
- 子(多側):外部キーを持ち、親を参照するエンティティ
・よって
・「入室管理用社員」→「入室許可」
・「室」→「入室許可」
・「入室管理用社員」→「入退室ログ」
・「室」→「入退室ログ」
が成立します。
- 図1の凡例に従い、4本の矢印(親→子)を描けば模範解答と一致します。
誤りやすいポイント
- ビュー表である「入室管理用社員」を“実表ではないから親にならない”と誤解する
- 「入室許可」と「入退室ログ」を直接結ぶ不要な関連を追加してしまう
- 親子の向きを逆(子→親)に描く
- “社員ID”“室ID”両方を含むからといって「入室許可」を親側に誤配置する
FAQ
Q: ビュー表でもE−R図に載せるのですか?
A: 【問題文】に「ビュー表を参照する方式を採用」と明記されているため、アプリケーションが実際に参照するビューは実体(エンティティ)として扱います。実表かビューかはE−R図の親子判定には影響しません。
A: 【問題文】に「ビュー表を参照する方式を採用」と明記されているため、アプリケーションが実際に参照するビューは実体(エンティティ)として扱います。実表かビューかはE−R図の親子判定には影響しません。
Q: 「入室許可」と「入退室ログ」を関連付けない理由は?
A: 「入退室ログ」は入退の事実を時系列で記録するだけで、許可情報そのものを保持していません。可否判定はアプリケーションが実行時に「入室許可」を参照して行うため、エンティティ間の直接参照は不要です。
A: 「入退室ログ」は入退の事実を時系列で記録するだけで、許可情報そのものを保持していません。可否判定はアプリケーションが実行時に「入室許可」を参照して行うため、エンティティ間の直接参照は不要です。
Q: 親子の向きを決める最短手順は?
A: ①外部キーを持つエンティティを一覧し、②その元となる主キーのエンティティを親とする、の2段階でほぼ判断できます。
A: ①外部キーを持つエンティティを一覧し、②その元となる主キーのエンティティを親とする、の2段階でほぼ判断できます。
関連キーワード: 外部キー, エンティティ関係, ビュー, 権限管理, 正規化
設問2:
問題文を見る表2に示した実表“入室許可”における、主キーを答えよ。
模範解答
社員ID, 室ID, 入室許可開始年月日
解説
解答の論理構成
- 主キーは「表の行を一意に識別する列(組)」である
- 【問題文】の「表2 入室管理システムで利用する主な表」で実表 “入室許可” の列は
・社員ID
・室ID
・入室許可開始年月日
・入室許可終了年月日 - 【問題文】のユースケース “入室許可登録” には
「既に実表 “入室許可” に同じ社員ID、室ID、入室許可開始年月日の行が存在する場合は、入室許可終了年月日を更新する。」
と記載されている - すでに行があるか否かの判定条件が「社員ID」+「室ID」+「入室許可開始年月日」の3項目だけで行われている
- したがって、この3項目の組が唯一性を担保しており、主キーに採用される
結論:主キーは「社員ID, 室ID, 入室許可開始年月日」です。
誤りやすいポイント
- 「入室許可終了年月日」まで含めた4列を主キーと誤認する
→ 更新対象行の検索条件に使われていない点に注意 - 一意制約の根拠を表構造だけで判断し、ユースケース(業務ルール)を見落とす
- 「社員ID」のみを主キーにしてしまい、同一社員が複数室へ入室許可を持つケースを想定し忘れる
FAQ
Q: 「入室許可終了年月日」を主キーに含めないと日付範囲が重複しませんか?
A: 重複有無はアプリケーションや別の制約で管理できます。主キーは行識別用であり、ユースケースが示すように識別に必要なのは3列です。
A: 重複有無はアプリケーションや別の制約で管理できます。主キーは行識別用であり、ユースケースが示すように識別に必要なのは3列です。
Q: なぜ「室ID」を外してはいけないのですか?
A: 同じ社員が複数の室に別々の期間で許可を持つ可能性があるため、「社員ID」だけでは一意になりません。
A: 同じ社員が複数の室に別々の期間で許可を持つ可能性があるため、「社員ID」だけでは一意になりません。
Q: 複合主キーを避けてサロゲートキー(連番)を設ける方法は適切ですか?
A: 実務では有効ですが、本設問は業務識別子ベースで主キーを設定しているので、問題の前提に従います。
A: 実務では有効ですが、本設問は業務識別子ベースで主キーを設定しているので、問題の前提に従います。
関連キーワード: 主キー、複合キー、一意制約、エンティティ、データモデリング
設問3:
問題文を見る図2中のaに入れる適切な字句を答えよ。
模範解答
a:COUNT(*)
解説
解答の導き方
まず設問の要求を確認します。問題文は「入室可否をチェックし、否の場合は0を、可の場合は1以上を返す」と明示しています。図2のSQLは次の形になっています。
「SELECT [a] FROM ROOM.入室許可 WHERE社員ID = :社員ID
AND 室ID = :室ID
AND 入室許可開始年月日 <= :今日
AND 入室許可終了年月日 >= :今日」
「SELECT [a] FROM ROOM.入室許可 WHERE社員ID = :社員ID
AND 室ID = :室ID
AND 入室許可開始年月日 <= :今日
AND 入室許可終了年月日 >= :今日」
ここで考えるべきことを順に示します。
-
WHERE句の条件は「社員ID と 室ID と 今日が入室許可期間内か」を満たす行を ROOM.入室許可 から抽出することを示しています。表3のユースケースにも「実表 “入室許可” で入室可否をチェックする」とあるので、この抽出結果が「許可の行」の集合に対応します。
-
求める戻り値は「0(許可なし)」または「1以上(許可あり)」の単一の数値です。FROMで複数行が得られる可能性があるため、得られた行集合を単一の値に集約する必要があります。単に列名をSELECTすると行ごとに結果が返り、件数ゼロのときは結果行自体が存在しない(0という行が返らない)ので要件を満たしません。
-
行数をそのまま返す集約関数として COUNT() が最も直接的かつ確実です。COUNT() は該当する行数を返し、該当行がなければ0、1行以上あればその件数(=1以上)を返します。これが設問の「否の場合は0、可の場合は1以上」をそのまま満たします。
-
COUNT(列名) と COUNT() の違いに注意します。COUNT(列名) はその列がNULLでない行のみを数えるため、列にNULLが入り得る場合に結果が変わる可能性があります。ROWを単純に数える目的では COUNT() が適切です。
したがって、図2の [a] には次を入れます。
SELECT COUNT(*) FROM ROOM.入室許可
WHERE 社員ID = :社員ID
AND 室ID = :室ID
AND 入室許可開始年月日 <= :今日
AND 入室許可終了年月日 >= :今日
WHERE 社員ID = :社員ID
AND 室ID = :室ID
AND 入室許可開始年月日 <= :今日
AND 入室許可終了年月日 >= :今日
結論:[a] に入れる適切な字句は COUNT(*) です。
誤りやすいポイント
- SELECT に列名(例えば 社員ID)を入れる:該当行が複数あると複数行が返り、該当行が0件のときは「0」という行が返らないため要件に合いません。
- COUNT(列名) を使う誤り:列にNULLが入る可能性があると期待した件数とずれることがあります。行数を確実に返すなら COUNT(*) が安全です。
- EXISTS をそのまま [a] に入れる誤解:EXISTS を使った判定は可能ですが、正しく使うにはクエリ構造をサブクエリ(あるいは CASE 式と組合せ)に書き換える必要があります。図2の「SELECT [a] FROM ROOM.入室許可 …」という骨組みのまま単純に EXISTS(...) を入れると、外側の FROM によって意図しない複数行が返るか、冗長な二重判定になってしまいます。
- 要件と実際の戻り値を取り違える:単に「可/否(真偽)」だけを返す(0/1)で十分な場合は COUNT() をさらに CASE で0/1に変換することもありますが、本問は「可の場合は1以上」を許容するため COUNT() がそのまま合致します。
FAQ
Q: COUNT() と COUNT(1) はどちらを使うべきですか?
A: 多くのRDBMSでは COUNT() と COUNT(1) は同じ結果を返し、実行計画上の差はほとんどありません。可読性と意図の明確さのために行数を数える場合は COUNT(*) を使うのが一般的です。
A: 多くのRDBMSでは COUNT() と COUNT(1) は同じ結果を返し、実行計画上の差はほとんどありません。可読性と意図の明確さのために行数を数える場合は COUNT(*) を使うのが一般的です。
Q: EXISTS を使って書けますか?
A: はい、可能です。ただし図2の構造を変える必要があります。例えば
SELECT CASE WHEN EXISTS(SELECT 1 FROM ROOM.入室許可 WHERE 社員ID = :社員ID AND 室ID = :室ID AND 入室許可開始年月日 <= :今日 AND 入室許可終了年月日 >= :今日) THEN 1 ELSE 0 END
のようにサブクエリと組合せる形になります(これだと可のときは常に1を返す点が COUNT(*) と異なります)。単に [a] に EXISTS(...) を書き換えるだけでは意図した単一の集計結果にならない点に注意してください。
A: はい、可能です。ただし図2の構造を変える必要があります。例えば
SELECT CASE WHEN EXISTS(SELECT 1 FROM ROOM.入室許可 WHERE 社員ID = :社員ID AND 室ID = :室ID AND 入室許可開始年月日 <= :今日 AND 入室許可終了年月日 >= :今日) THEN 1 ELSE 0 END
のようにサブクエリと組合せる形になります(これだと可のときは常に1を返す点が COUNT(*) と異なります)。単に [a] に EXISTS(...) を書き換えるだけでは意図した単一の集計結果にならない点に注意してください。
Q: 同一社員・同一室で複数の許可行があったとき、COUNT() は複数を返しますが、業務的に「1」を返したい場合はどうすればよいですか?
A: 集約した後に 0/1 に変換します。例:SELECT CASE WHEN COUNT() >= 1 THEN 1 ELSE 0 END FROM ... のように書くと業務要件に合わせて 0/1 にできます。
A: 集約した後に 0/1 に変換します。例:SELECT CASE WHEN COUNT() >= 1 THEN 1 ELSE 0 END FROM ... のように書くと業務要件に合わせて 0/1 にできます。
関連キーワード: COUNT(*), 集約関数, WHERE句, EXISTS, 相関サブクエリ
設問4:ビュー表“入室管理用社員”について、(1)、(2)に答えよ。
問題文を見る模範解答
b:GRANT
c:SELECT
d:HR.入室管理用社員
e:ROOM_AP
解説
解答の論理構成
-
ビュー表を「参照だけできるように」する
問題文では、 “このビュー表を入室管理システムのAPが参照だけできるように権限を付与する”
と記載されています。参照=SELECT 権限を付与することだと分かります。 -
権限付与は GRANT 句を用いる
RDBMS の標準 SQL では、権限付与は GRANT 構文を使用します。
したがって b には GRANT が入ります。 -
付与する権限は SELECT
参照のみを許可するため、INSERT や UPDATE ではなく SELECT を指定します。
よって c には SELECT が入ります。 -
権限の対象オブジェクト
ビュー表は “スキーマ名.表名” で表記するという指示があり、対象となるビューは
“HR.入室管理用社員” です。したがって d にはHR.入室管理用社員 が入ります。 -
以上を順に並べると
GRANT SELECT ON HR.入室管理用社員 TO ROOM_AP
となり、模範解答と合致します。
誤りやすいポイント
- SELECT 権限だけで良いところを、誤って ALL を付与してしまう。これでは「参照だけ」という要件を満たしません。
- ビュー表名の前にスキーマ名を付け忘れる。異なるスキーマ間で操作する場合、完全修飾名を省くと実行時に “表が見つからない” エラーが発生します。
- 権限の付与先としてDBA用ユーザ “ROOM_DBA” を書いてしまうケース。APが実際に接続するのは “ROOM_AP” です。
FAQ
Q: ビュー表にアクセスする際、基になる実表への権限も必要ですか?
A: 問題文の仕様(2)に“ビュー表にアクセスする場合、そのビュー表が参照する表のアクセス権限は不要である”とあるとおり、ビュー単体への権限だけで参照できます。
A: 問題文の仕様(2)に“ビュー表にアクセスする場合、そのビュー表が参照する表のアクセス権限は不要である”とあるとおり、ビュー単体への権限だけで参照できます。
Q: GRANT SELECT ON ... を発行できるのは誰ですか?
A: 表(またはビュー)所有者であるDBA、ここでは “HR_DBA” が発行します。“ROOM_DBA” や “ROOM_AP” には他スキーマのオブジェクトに対する権限付与はできません。
A: 表(またはビュー)所有者であるDBA、ここでは “HR_DBA” が発行します。“ROOM_DBA” や “ROOM_AP” には他スキーマのオブジェクトに対する権限付与はできません。
Q: 将来 UPDATE も許可したい場合はどうすればよいですか?
A: GRANT SELECT, UPDATE ON HR.入室管理用社員 TO ROOM_AP のように複数権限をカンマ区切りで追加します。ただし要件変更時は最小権限の原則を再確認しましょう。
A: GRANT SELECT, UPDATE ON HR.入室管理用社員 TO ROOM_AP のように複数権限をカンマ区切りで追加します。ただし要件変更時は最小権限の原則を再確認しましょう。
関連キーワード: RDBMS権限管理、GRANT文、ビュー、スキーマ、アクセス制御
設問4:ビュー表“入室管理用社員”について、(1)、(2)に答えよ。
問題文を見る(2)ビュー表を参照する権限を付与するSQL文を実行するユーザ名を答えよ。
模範解答
HR_DBA
解説
解答の論理構成
-
ビュー表 “入室管理用社員” はスキーマ “HR” に属します。
――【問題文】「CREATE VIEW HR.入室管理用社員 …」
したがって、このビューの所有者は “HR” スキーマのDBAです。 -
各システムのDBA/APユーザは次のとおりです。
――【問題文】表4「人事システム」「スキーマ名HR」「DBA用ユーザ名HR_DBA」
所有者は “HR_DBA”、参照したい入室管理システムのAPユーザは “ROOM_AP” です。 -
アクセス権限の付与は所有者だけが行える、という仕様があります。
――【問題文】(1)「表のデータに対して、所有者以外のユーザが参照…を行うためには…所有者から付与してもらう必要がある。」 -
したがって、ビュー表を参照する権限を付与する SQL 文(GRANT 文)を実行できるのは、所有者 “HR_DBA” です。
誤りやすいポイント
- GRANT 文の実行者を「付与される側(ROOM_AP)」と勘違いする。付与は所有者が行う点に注意。
- 「ビューだから所有者は不要」と早合点する。ビューも格納スキーマのオブジェクトであり、所有者権限が必要です。
- スキーマ名 “HR” を見落として “ROOM_DBA” と答えてしまうケース。スキーマとシステムをセットで確認することが大切です。
FAQ
Q: ビュー表の場合でも所有者が権限を付与する必要がありますか?
A: はい。【問題文】(1) の仕様はビューにも適用されます。
A: はい。【問題文】(1) の仕様はビューにも適用されます。
Q: AP ユーザが自分で GRANT 文を実行してはいけないのですか?
A: APユーザは所有者ではないので実行権限がありません。所有者 “HR_DBA” が代わりに実行します。
A: APユーザは所有者ではないので実行権限がありません。所有者 “HR_DBA” が代わりに実行します。
Q: DBA以外にシステム管理者アカウントで付与しても良いですか?
A: 試験問題の前提では、表の所有者=各システムのDBAと定義されているため、想定される実行者は “HR_DBA” です。
A: 試験問題の前提では、表の所有者=各システムのDBAと定義されているため、想定される実行者は “HR_DBA” です。
関連キーワード: GRANT, 権限管理、スキーマ、ビュー、所有者
設問5:
問題文を見る図5中のfに入れる適切な式を答えよ。
模範解答
f:T1.所属組織ID = T3.組織ID AND T3.組織長の社員ID = T2.社員ID
解説
解答の論理構成
-
追加事項の確認
【問題文】には、ビュー表を修正した理由として
“管理者は、‘申請者が入室希望社員の組織長であること’を確認することになった。そのため、ビュー表“入室管理用社員”に組織長の氏名が必要となり”
とあります。したがって新しい列 “組織長氏名” は「組織長本人が ‘社員’ 表に登録している “氏名”」を取り出す必要があります。 -
参照すべき実表と列
表1の実表 “社員” には
“社員ID、氏名、…、所属組織ID”
があり、実表 “組織” には
“組織ID、組織名、組織長の社員ID”
が定義されています。
・入室希望社員(T1)は “所属組織ID” を持つ
・その “所属組織ID” が参照する実表 “組織” の主キーは “組織ID”
・同じ “組織” 行には “組織長の社員ID” が格納される
・組織長本人の “氏名” は再び実表 “社員” から取得できる -
結合パスの確定
上記より、(入室希望社員)と (組織)は
T1.所属組織ID = T3.組織ID
で結合。
次に、(組織)と (組織長)は
T3.組織長の社員ID = T2.社員ID
で結合。 -
式の完成
2つの結合条件を AND で連結すれば良いので、f には
T1.所属組織ID = T3.組織ID AND T3.組織長の社員ID = T2.社員ID
が入ります。
誤りやすいポイント
- “組織長の社員ID” を直接 “所属組織ID” に結合してしまう
→ 列同士の意味が異なり、論理的整合性を欠きます。 - “組織長氏名” を取得するためにサブクエリを使おうとする
→ 本問は単純な内部結合で十分です。 - 列名のタイポや別名の付与忘れ
→ 試験では “社員ID” と “社員ID”、“組織長の社員ID” のように空白の有無も区別されるので注意が必要です。
FAQ
Q: 自己結合ではなく3表結合にした理由は?
A: “組織長の社員ID” は実表 “組織” にあり、組織長本人の “氏名” は実表 “社員” にあるため、間に “組織” 表を挟んだ3表結合が最小構成です。
A: “組織長の社員ID” は実表 “組織” にあり、組織長本人の “氏名” は実表 “社員” にあるため、間に “組織” 表を挟んだ3表結合が最小構成です。
Q: ビュー表経由で参照するとき、基となる実表の権限は不要ですか?
A: 【問題文】“(2) ビュー表にアクセスする場合、そのビュー表が参照する表のアクセス権限は不要である。” とある通り、ビューに対する SELECT 権限さえあれば基表の権限は不要です。
A: 【問題文】“(2) ビュー表にアクセスする場合、そのビュー表が参照する表のアクセス権限は不要である。” とある通り、ビューに対する SELECT 権限さえあれば基表の権限は不要です。
Q: “組織長氏名” を取得するのに LEFT JOIN を使うべきですか?
A: 本問では入室希望社員には必ず所属組織が設定され、組織には必ず組織長が登録されている前提なので INNER JOIN(WHERE 句による等価結合)で問題ありません。
A: 本問では入室希望社員には必ず所属組織が設定され、組織には必ず組織長が登録されている前提なので INNER JOIN(WHERE 句による等価結合)で問題ありません。
関連キーワード: ビュー表、内部結合、自己結合、アクセス権限、射影








