以下討論提供數個範例,說明 MySQL 如何偵測函數依賴性。範例使用以下表示法
{X} -> {Y}請理解為 「X 唯一決定 Y,」,這也表示 Y 在功能上依賴於 X。
範例使用 world 資料庫,該資料庫可從 https://dev.mysql.com.tw/doc/index-other.html 下載。您可以在同一個頁面找到如何安裝資料庫的詳細資訊。
以下查詢選取每個國家/地區的口語語言計數
SELECT co.Name, COUNT(*)
FROM countrylanguage cl, country co
WHERE cl.CountryCode = co.Code
GROUP BY co.Code;
co.Code 是 co 的主索引鍵,因此 co 的所有欄位在功能上都依賴於它,如使用以下表示法所表示
{co.Code} -> {co.*}因此,co.name 在功能上依賴於 GROUP BY 欄位,並且查詢有效。
可以使用 NOT NULL 欄位上的 UNIQUE 索引來取代主索引鍵,且會套用相同的函數依賴性。(對於允許 NULL 值的 UNIQUE 索引而言,情況並非如此,因為它允許多個 NULL 值,在這種情況下,唯一性會遺失。)
此查詢選取每個國家/地區的所有口語語言清單以及使用這些語言的人數
SELECT co.Name, cl.Language,
cl.Percentage * co.Population / 100.0 AS SpokenBy
FROM countrylanguage cl, country co
WHERE cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;(cl.CountryCode, cl.Language) 這一對是 cl 的雙欄複合主索引鍵,因此該欄位對會唯一決定 cl 的所有欄位
{cl.CountryCode, cl.Language} -> {cl.*}此外,由於 WHERE 子句中的等式
{cl.CountryCode} -> {co.Code}而且,因為 co.Code 是 co 的主索引鍵
{co.Code} -> {co.*}「唯一決定」關係是可傳遞的,因此
{cl.CountryCode, cl.Language} -> {cl.*,co.*}因此,查詢有效。
與先前的範例相同,可以使用 NOT NULL 欄位上的 UNIQUE 索引來取代主索引鍵。
可以使用 INNER JOIN 條件來取代 WHERE。會套用相同的函數依賴性
SELECT co.Name, cl.Language,
cl.Percentage * co.Population/100.0 AS SpokenBy
FROM countrylanguage cl INNER JOIN country co
ON cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;
雖然 WHERE 條件或 INNER JOIN 條件中的等式測試是對稱的,但外部聯結條件中的等式測試卻不是,因為表格扮演不同的角色。
假設參考完整性意外中斷,且 countrylanguage 中存在一列,但 country 中沒有對應的列。考量與先前範例相同的查詢,但使用 LEFT JOIN
SELECT co.Name, cl.Language,
cl.Percentage * co.Population/100.0 AS SpokenBy
FROM countrylanguage cl LEFT JOIN country co
ON cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;對於給定的 cl.CountryCode 值,聯結結果中的 co.Code 值會在相符的列中找到 (由 cl.CountryCode 決定),如果沒有相符項目 (也由 cl.CountryCode 決定),則會以 NULL 來補齊。在每種情況下,此關係都適用
{cl.CountryCode} -> {co.Code}
cl.CountryCode 本身在功能上依賴於 {cl.CountryCode, cl.Language},這是主索引鍵。
如果在聯結結果中,co.Code 是以 NULL 值補齊的,則 co.Name 也會是。如果 co.Code 不是以 NULL 值補齊的,則因為 co.Code 是一個主鍵,它會決定 co.Name。因此,在所有情況下
{co.Code} -> {co.Name}這會產生
{cl.CountryCode, cl.Language} -> {cl.*,co.*}因此,查詢有效。
然而,假設表格交換了,如同這個查詢一樣
SELECT co.Name, cl.Language,
cl.Percentage * co.Population/100.0 AS SpokenBy
FROM country co LEFT JOIN countrylanguage cl
ON cl.CountryCode = co.Code
GROUP BY cl.CountryCode, cl.Language;現在這種關係不適用
{cl.CountryCode, cl.Language} -> {cl.*,co.*}事實上,所有為 cl 建立的 NULL 值補齊的列都會被放入單一群組(它們的 GROUP BY 欄位都等於 NULL),而且在這個群組內,co.Name 的值可能會有所不同。這個查詢是無效的,MySQL 會拒絕它。
外部聯結中的函數相依性因此與決定性欄位屬於 LEFT JOIN 的左側或右側有關。如果存在巢狀外部聯結,或聯結條件不完全由等式比較組成,則函數相依性的判定會變得更加複雜。
假設一個關於國家的視圖產生了它們的代碼、大寫的名稱以及它們有多少種不同的官方語言
CREATE VIEW country2 AS
SELECT co.Code, UPPER(co.Name) AS UpperName,
COUNT(cl.Language) AS OfficialLanguages
FROM country AS co JOIN countrylanguage AS cl
ON cl.CountryCode = co.Code
WHERE cl.isOfficial = 'T'
GROUP BY co.Code;這個定義是有效的,因為
{co.Code} -> {co.*}在視圖結果中,第一個選取的欄位是 co.Code,它也是群組欄位,因此決定了所有其他選取的表達式
{country2.Code} -> {country2.*}MySQL 理解這一點並使用此資訊,如下所述。
這個查詢顯示了國家、它們有多少種不同的官方語言以及它們有多少個城市,透過將視圖與 city 表格聯結
SELECT co2.Code, co2.UpperName, co2.OfficialLanguages,
COUNT(*) AS Cities
FROM country2 AS co2 JOIN city ci
ON ci.CountryCode = co2.Code
GROUP BY co2.Code;這個查詢是有效的,因為,如先前所見
{co2.Code} -> {co2.*}MySQL 能夠發現視圖結果中的函數相依性,並使用它來驗證使用視圖的查詢。如果 country2 是一個衍生表格(或通用表格表達式),情況也會相同,如同
SELECT co2.Code, co2.UpperName, co2.OfficialLanguages,
COUNT(*) AS Cities
FROM
(
SELECT co.Code, UPPER(co.Name) AS UpperName,
COUNT(cl.Language) AS OfficialLanguages
FROM country AS co JOIN countrylanguage AS cl
ON cl.CountryCode=co.Code
WHERE cl.isOfficial='T'
GROUP BY co.Code
) AS co2
JOIN city ci ON ci.CountryCode = co2.Code
GROUP BY co2.Code;