# 12.20.4 检测功能依赖
下面的讨论提供了 MySQL 检测功能依赖关系的几个示例。示例使用此表示法:
{X} -> {Y}
将其理解为“X
唯一确定是
,”这也意味着*是
在功能上取决于X
*.
示例使用世界
数据库,可以从https://dev.mysql.com/doc/index-other.html (opens new window).您可以在同一页面上找到有关如何安装数据库的详细信息。
# 从键派生的功能依赖
以下查询为每个国家/地区选择口语计数:
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 能够结合前面所有类型的函数依赖(基于键、基于相等、基于视图)来验证更复杂的查询。