110 公務人員升官等薦任 資訊處理 資料庫應用 考古題詳解
第 一 題25 分
請試述下列名詞之意涵:(每小題 5 分,共 25 分)
(1) Replication independence in a distributed database system
(2) B+-tree
(3) Entity integrity rule
(4) Boyce-Codd Normal Form(BCNF)
(5) NOSQL
登入後即可作答並保存紀錄。
核心觀念
本題考查資料庫系統的五個基礎名詞,涵蓋分散式資料庫、索引結構、關聯式完整性限制、正規化,以及非關聯式資料庫。作答時要抓住各名詞的定義、目的與關鍵特徵,並適度區分容易混淆的概念。
解題方法
逐一以「是什麼、解決什麼問題、具備哪些特徵」說明。定義題不需推導計算,但應寫出足以辨識概念的核心條件,尤其是 BCNF 的函數相依判準,以及 Entity Integrity Rule 對主鍵的限制。
(1) Replication independence in a distributed database system
複本獨立性是分散式資料庫的一種資料獨立性:資料庫即使在多個節點或站台保存同一資料的複本,使用者或應用程式仍可像存取單一資料庫一樣操作資料,而不必知道複本的數量、位置或實際存取哪一份。
資料庫管理系統負責選擇讀取的複本,並處理新增、修改、刪除資料時的複本同步與一致性。其目的在降低複本配置對應用程式的影響,並可提升可用性與讀取效能。
**辨析:**複本獨立性處理的是「有幾份資料副本,以及副本放在哪裡」;位置獨立性則處理「資料分布在哪個站台」。
(2) B+-tree
**B+-tree(B+ 樹)**是資料庫常用的平衡多路搜尋樹,適合磁碟索引。其主要特徵如下:
- 內部節點保存搜尋鍵及子節點指標,用於導引搜尋。
- 所有資料記錄的指標(或記錄本身)都保存在葉節點;內部節點的鍵值是搜尋用的分隔鍵。
- 葉節點通常依鍵值順序連結,方便範圍查詢及排序掃描。
- 樹保持平衡,所有葉節點位於相同深度,因此搜尋、插入與刪除的成本通常與樹高相關。
B+ 樹的節點可容納多個鍵值,樹高通常較低,能減少磁碟 I/O。葉節點的順序連結則使範圍查詢比逐筆搜尋更有效率。
(3) Entity integrity rule
實體完整性規則要求關聯表的主鍵值必須唯一,且主鍵的任何欄位都不得為 NULL。
主鍵用來識別每一筆資料列;若主鍵重複,就無法區分資料列;若主鍵為 NULL,則無法確定資料列的識別值。因此,主鍵須同時具備唯一性與非空性。
**辨析:**Entity Integrity Rule 規範主鍵;參照完整性則規範外鍵值必須符合被參照資料列的主鍵,或依規則允許為 NULL。
(4) Boyce-Codd Normal Form(BCNF)
第 二 題15 分
假設我們有一個投資公司的資料庫,包含以下屬性:
- :Broker
- :Office of a broker
- :Investor
- :Stock
- :Quantity of stock owned by an investor
- :Dividend paid by a stock
整體 schema 為 。
假設此資料庫有以下 functional dependencies:
(1) 列舉所有 的 candidate keys。(5 分)
(2) 寫出一個 lossless-join 分解,使得 分解後滿足 BCNF。(10 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查函數相依(functional dependency, FD)、candidate key 的求法,以及將關聯分解至 BCNF 並保持無損連接。
若 ,表示任意兩筆資料只要在 的值相同, 的值也必須相同。屬性集 的閉包 ,是由已知 FD 推得的所有屬性。若 ,則 是 superkey;若 又沒有可刪除的屬性仍維持 superkey,便是 candidate key。
關聯符合 BCNF 的條件是:對每個非平凡 FD , 都必須是該關聯的 superkey。違反此條件時,可依該 FD 分解成 與 ;因交集 且 ,此分解為 lossless-join。
解題方法
先利用閉包找出 candidate keys,再逐一檢查違反 BCNF 的 FD,套用無損分解公式,直到每個子關聯均符合 BCNF。
(1)列舉所有 candidate keys
檢視 FD 右側屬性: 都出現在右側; 沒有出現在任何 FD 的右側。因此,要決定 與 的值,任何可決定全體屬性的 key 都必須包含 。
計算 的閉包:
所以 是 superkey。由於 、 都必須包含在任何 key 中,且 已能決定所有屬性,因此不能再刪除其中任一屬性; 是 candidate key,也是唯一的 candidate key。
(2)分解為 lossless-join 的 BCNF
原關聯 的 candidate key 為 。因此,、、 的決定項都不是 的 superkey,皆違反 BCNF。依序分解如下:
第一步:依 分解
交集為 ,而 ,故此步為 lossless-join。
第 三 題20 分
(1) 請解釋何謂 SQL injection,以及要如何預防?(10 分)
(2) 常見的 SQL injection 攻擊手法為「略過權限檢查」與「注入 SQL 子語法」等,請寫出一段有 SQL injection 漏洞的網頁程式碼,以及可能的 SQL injection 攻擊寫法。(10 分)
登入後即可作答並保存紀錄。
核心觀念
SQL injection(SQL 注入)是指程式將使用者輸入直接拼接進 SQL 指令,導致輸入內容被資料庫當成 SQL 語法執行。攻擊者可能藉此略過登入或權限檢查、讀取或竄改資料,甚至刪除資料。
本題考查的是:使用者輸入如何改變 SQL 指令的語意,以及如何讓輸入維持為「資料」而非「可執行語法」。本題不涉及特定法條。
解題方法
(1)SQL injection 的預防
預防的核心是避免把未信任輸入直接串接到 SQL 指令中:
- 使用參數化查詢或預備陳述式:SQL 結構先固定,再以參數傳入使用者輸入。資料庫會將參數視為資料,不會把其中的引號或 SQL 關鍵字當成指令執行。
- 檢查輸入格式:依欄位需求驗證型別、長度、格式與允許值,例如帳號只能包含規定的字元。輸入驗證是額外防線,不能取代參數化查詢。
- 避免動態拼接 SQL:若表名、欄位名或排序方式無法用參數傳入,應以程式內的固定白名單選取,不可直接採用使用者提供的字串。
- 限制資料庫帳號權限:應用程式帳號只授予完成業務所需的最低權限,避免注入後造成不必要的資料讀取、修改或刪除。
- 妥善處理錯誤訊息:對外不顯示資料庫錯誤細節,以免暴露資料表、欄位或查詢結構;錯誤應記錄於受控的伺服器端紀錄。
輸入過濾或跳脫特殊字元不能單獨取代參數化查詢,因為不同資料庫、字元集與查詢情境可能有不同處理方式。
(2)有漏洞的程式碼與攻擊寫法
以下以 PHP 與 MySQL 為例。程式直接把使用者輸入串接到 SQL,因而有注入漏洞:
<?php
$username = $_POST['username'];
$password = $_POST['password'];
$sql = "SELECT * FROM users
WHERE username = '$username'
AND password = '$password'";
$result = mysqli_query($conn, $sql);
if (mysqli_num_rows(
第 四 題40 分
根據以下關聯資料表架構,老師可開設多門課程,同一門課可以有多位教師,學生也可以修多門課程,修過課程就會有分數。
- :學生編號、姓名、年紀、性別
- :課程編號、課名、教師編號
- :教師編號、教師名稱
- :學生編號、課程編號、分數
寫出以下 SQL 查詢:
(1) 查詢學生名字中含有「Alan」的男學生人數。(5 分)
(2) 查詢 Alan 修過的課中,那門課只由一位老師開課的課程名稱。(5 分)
(3) 查詢修過課程所有成績之平均成績大於等於 60 分的同學之學生編號、學生姓名和平均成績。(10 分)
(4) 查詢學過編號為「01」但是沒有學過編號為「02」課程的同學編號與其修「01」課的分數。(10 分)
(5) 查詢沒有學過全部課程的同學之編號。(10 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查 SQL 的條件篩選、表格連接、彙總函數、分組篩選,以及集合中的「存在」與「全稱」判斷。
依題目架構,score(SID,CID,sc) 記錄學生修課及分數;course(CID,Cname,TID) 每筆課程資料只有一個 TID,因此此架構本身將每門課對應到一位教師。第(2)小題所說「只由一位老師開課」,依此架構解讀為該課程在 course 表中只有一筆資料。
解題方法
(1)名字含有 Alan 的男學生人數
以 LIKE '%Alan%' 篩選姓名中包含 Alan 的學生,再用性別條件篩選男學生,最後以 COUNT(*) 計算人數。
SELECT COUNT(*) AS student_count
FROM student
WHERE Sname LIKE '%Alan%'
AND Ssex = '男';
% 代表任意長度的字串,因此 Alan 出現在姓名的開頭、中間或結尾都會符合條件。
(2)Alan 修過且只由一位老師開課的課程名稱
先從 student 找出姓名包含 Alan 的學生,再透過 score 找出其修過的課程,最後連接 course 取得課名。依題目資料架構,每筆課程只有一個教師編號,所以符合架構的課程即為只由一位教師開課的課程。
SELECT DISTINCT c.Cname
FROM student s
JOIN score sc ON sc.SID = s.SID
JOIN course c ON c.CID = sc.CID
WHERE s.Sname LIKE '%Alan%';
使用 DISTINCT 可避免同一課程因多位符合姓名條件的學生修習,或資料重複而重複列出。
(3)平均成績至少 60 分的同學
先按學生分組,使用 AVG(sc) 計算每位學生的平均成績,再以 HAVING 篩選平均成績至少 60 分的學生。因為還要輸出姓名,需連接 student 表。
SELECT s.SID, s.Sname, AVG(sc.sc) AS avg_score
FROM student s
JOIN score sc ON sc.SID = s.SID
GROUP BY s.SID, s.Sname
HAVING AVG(sc.sc) >= 60;