このページは機械翻訳したものです。
次の説明では、MySQL が関数従属性を検出する方法の例をいくつか示します。 この例では、次の表記法を使用します:
{X} -> {Y}
これを「「X は、Y を一意に決定」」として理解します。つまり、Y は機能的に X に依存しています。
この例では、https://dev.mysql.com/doc/index-other.html からダウンロードできる world データベースを使用します。 データベースのインストール方法の詳細は、同じページを参照してください。
次のクエリーは、国ごとに話された言語の数を選択します:
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 値が許可され、その場合は一意性が失われるため、NULL 値を許可する UNIQUE インデックスには当てはまりません。)
このクエリーでは、国ごとに、すべての話し言葉のリストとそれらを話すユーザーの数を選択します:
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 の 2 カラム複合主キーであるため、カラムのペアによって 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 キーを主キーのかわりに使用できます。
WHERE のかわりに INNER JOIN 条件を使用できます。 同じ機能依存性が適用されます:
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 によって決定) で検出されるか、一致がない場合は NULL で補完されます (cl.CountryCode によっても決定されます)。 いずれの場合も、この関係が適用されます:
{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;