### 12.20.4 检测功能依赖

[](<>)

下面的讨论提供了 MySQL 检测功能依赖关系的几个示例。示例使用此表示法：

```
{X} -> {Y}
```

将其理解为“*`X`*唯一确定*`是`*,”这也意味着*`是`*在功能上取决于*`X`*.

示例使用`世界`数据库，可以从<https://dev.mysql.com/doc/index-other.html>.您可以在同一页面上找到有关如何安装数据库的详细信息。

-   [从键派生的功能依赖](group-by-functional-dependence.html#functional-dependence-keys)

-   [从多列键和等式派生的功能依赖关系](group-by-functional-dependence.html#functional-dependence-multiple-column-keys)

-   [功能依赖特例](group-by-functional-dependence.html#functional-dependence-special-cases)

-   [功能依赖和视图](group-by-functional-dependence.html#functional-dependence-views)

-   [功能依赖的组合](group-by-functional-dependence.html#functional-dependence-combinations)

#### 从键派生的功能依赖

以下查询为每个国家/地区选择口语计数：

```
SELECT co.Name, COUNT(*)
FROM countrylanguage cl, country co
WHERE cl.CountryCode = co.Code
GROUP BY co.Code;
```

`代码`是一个主键`合作`, 所以所有列`合作`在功能上依赖于它，如使用此符号表示：

```
{co.Code} -> {co.*}
```

因此，`同名`在功能上取决于`通过...分组`列并且查询有效。

一种`独特`索引超过`非空`可以使用列代替主键，并且将应用相同的功能依赖性。（这对于一个`独特`允许的索引`空值`值，因为它允许多个`空值`值，在这种情况下，唯一性就会丢失。）

#### 从多列键和从

平等

此查询为每个国家/地区选择所有使用语言的列表以及使用这些语言的人数：

```
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.CountryCode, cl.Language} -> {cl.*}
```

此外，由于平等`在哪里`条款：

```
{cl.CountryCode} -> {co.Code}
```

而且，因为`代码`是主键`合作`：

```
{co.Code} -> {co.*}
```

“唯一确定”的关系是可传递的，因此：

```
{cl.CountryCode, cl.Language} -> {cl.*,co.*}
```

结果，查询是有效的。

与前面的示例一样，一个`独特`关键`非空`可以使用列代替主键。

一个`内部联接`可以使用条件代替`在哪里`.相同的功能依赖项适用：

```
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;
```

#### 功能依赖特例

而在一个平等测试`在哪里`条件或`内部联接`条件是对称的，外连接条件中的相等性测试不是，因为表扮演不同的角色。

假设参照完整性被意外破坏并且存在一行`国家语言`没有对应的行`国家`.考虑与上一个示例中相同的查询，但使用`左连接`：

```
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`， 的价值`代码`在连接结果中要么在匹配的行中找到（由`cl.CountryCode`) 或者是`空值`- 如果没有匹配则补充（也由`cl.CountryCode`）。在每种情况下，这种关系都适用：

```
{cl.CountryCode} -> {co.Code}
```

`cl.CountryCode`本身在功能上依赖于 {`cl.CountryCode`,`分类语言`} 这是一个主键。

如果在连接结果中`代码`是`空值`-补充，`同名`也是。如果`代码`不是`空值`-互补，然后因为`代码`是主键，它决定`同名`.因此，在所有情况下：

```
{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.*}
```

的确，所有`空值`-为完成的行`分类`被放入一个组中（他们都有`通过...分组`列等于`空值`)，并且在这个组内的值`同名`可以变化。查询无效，MySQL 拒绝它。

因此，外连接中的功能依赖与行列式列属于左侧还是右侧相关联。`左连接`.如果存在嵌套的外部连接或连接条件不完全由相等比较组成，则函数依赖的确定会变得更加复杂。

#### 功能依赖和视图

假设一个国家的视图产生了他们的代码、他们的大写名字，以及他们有多少不同的官方语言：

```
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.*}
```

在视图结果中，第一个选择的列是`代码`，它也是组列，因此确定所有其他选定的表达式：

```
{country2.Code} -> {country2.*}
```

MySQL 理解这一点并使用此信息，如下所述。

此查询通过将视图与`城市`桌子：

```
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 能够发现视图结果中的功能依赖关系，并使用它来验证使用该视图的查询。如果`国家2`是派生表（或公用表表达式），如：

```
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;
```

#### 功能依赖的组合

MySQL 能够结合前面所有类型的函数依赖（基于键、基于相等、基于视图）来验证更复杂的查询。
