The following discussion provides several examples of the ways in which MySQL detects functional dependencies. 下面的讨论提供了几个MySQL检测函数依赖关系的方法示例。The examples use this notation:示例使用此符号:
{X
} -> {Y
}
Understand this as “把它理解为“X
uniquely determines Y
,” which also means that Y
is functionally dependent on X
.X
唯一地决定Y
”,这也意味着Y
在功能上依赖于X
。
The examples use the 这些示例使用的是world
database, which can be downloaded from https://dev.mysql.com/doc/index-other.html. world
数据库,可以从https://dev.mysql.com/doc/index-other.html下载到。You can find details on how to install the database on the same page.您可以在同一页上找到有关如何安装数据库的详细信息。
The following query selects, for each country, a count of spoken languages:以下查询为每个国家选择一个口语计数:
SELECT co.Name, COUNT(*) FROM countrylanguage cl, country co WHERE cl.CountryCode = co.Code GROUP BY co.Code;
co.Code
is a primary key of co
, so all columns of co
are functionally dependent on it, as expressed using this notation:co.Code
是co
的主键,因此co
的所有列在功能上都依赖于它,如使用以下符号表示的:
{co.Code} -> {co.*}
Thus, 因此,co.name
is functionally dependent on GROUP BY
columns and the query is valid.co.name
在功能上依赖于GROUP BY
列,查询是有效的。
A 可以使用UNIQUE
index over a NOT NULL
column could be used instead of a primary key and the same functional dependence would apply. NOT NULL
列上的UNIQUE
索引代替主键,并应用相同的函数依赖关系。(This is not true for a (对于允许空值的UNIQUE
index that permits NULL
values because it permits multiple NULL
values and in that case uniqueness is lost.)UNIQUE
索引,这是不正确的,因为它允许多个NULL
值,在这种情况下,唯一性将丢失。)
This query selects, for each country, a list of all spoken languages and how many people speak them:此查询为每个国家选择所有口语的列表以及说这些语言的人数:
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;
The pair (cl.CountryCode
, cl.Language
) is a two-column composite primary key of cl
, so that column pair uniquely determines all columns of cl
:
{cl.CountryCode, cl.Language} -> {cl.*}
Moreover, because of the equality in the 此外,由于WHERE
clause:WHERE
子句中的平等性:
{cl.CountryCode} -> {co.Code}
And, because 又因为co.Code
is primary key of co
:co.Code
是co
的主键:
{co.Code} -> {co.*}
“Uniquely determines” relationships are transitive, therefore:“唯一决定”关系是可传递的,因此:
{cl.CountryCode, cl.Language} -> {cl.*,co.*}
As a result, the query is valid.因此,查询是有效的。
As with the previous example, a 与前面的示例一样,可以使用UNIQUE
key over NOT NULL
columns could be used instead of a primary key.NOT NULL
列上的UNIQUE
键来代替主键。
An 可以使用INNER JOIN
condition can be used instead of WHERE
. INNER JOIN
条件代替WHERE
。The same functional dependencies apply:同样的函数依赖关系也适用于:
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;
Whereas an equality test in a WHERE
condition or INNER JOIN
condition is symmetric, an equality test in an outer join condition is not, because tables play different roles.WHERE
条件或INNER JOIN
条件中的相等性测试是对称的,而OUTER JOIN
条件中的相等性测试不是对称的,因为表扮演不同的角色。
Assume that referential integrity has been accidentally broken and there exists a row of 假设引用完整性被意外破坏,并且存在countrylanguage
without a corresponding row in country
. countrylanguage
行,而country
中没有相应的行。Consider the same query as in the previous example, but with a 考虑与上一个示例中相同的查询,但使用左联接: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;
For a given value of 对于给定的cl.CountryCode
, the value of co.Code
in the join result is either found in a matching row (determined by cl.CountryCode
) or is NULL
-complemented if there is no match (also determined by cl.CountryCode
). cl.CountryCode
值,联接结果中co.Code
的值要么在匹配行中找到(由cl.CountryCode
确定),要么在不匹配的情况下补为空(也由cl.CountryCode
确定)。In each case, this relationship applies:在每种情况下,这种关系都适用于:
{cl.CountryCode} -> {co.Code}
cl.CountryCode
is itself functionally dependent on {cl.CountryCode
, cl.Language
} which is a primary key.cl.CountryCode
本身在功能上依赖于{cl.CountryCode, cl.Language}
,后者是主键。
If in the join result 如果在连接结果中co.Code
is NULL
-complemented, co.Name
is as well. co.Code
是空的,那么co.Name
也是空的。If 如果co.Code
is not NULL
-complemented, then because co.Code
is a primary key, it determines co.Name
. co.Code
不是空的补码,那么因为co.Code
是主键,所以它决定co.Name
。Therefore, in all cases:因此,在所有情况下:
{co.Code} -> {co.Name}
Which yields:由此产生:
{cl.CountryCode, cl.Language} -> {cl.*,co.*}
As a result, the query is valid.因此,查询是有效的。
However, suppose that the tables are swapped, as in this query:但是,假设表已交换,如以下查询中所示:
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;
Now this relationship does not apply:现在这种关系不适用:
{cl.CountryCode, cl.Language} -> {cl.*,co.*}
Indeed, all 实际上,为NULL
-complemented rows made for cl
is put into a single group (they have both GROUP BY
columns equal to NULL
), and inside this group the value of co.Name
can vary. cl
生成的所有NULL
补码行都放在一个组中(它们的GROUP BY
列都等于NULL
),并且在这个组中co.Name
的值可以不同。The query is invalid and MySQL rejects it.该查询无效,MySQL拒绝该查询。
Functional dependence in outer joins is thus linked to whether determinant columns belong to the left or right side of the 因此,外部联接中的函数依赖性与行列式列属于LEFT JOIN
. LEFT JOIN
的左侧还是右侧有关。Determination of functional dependence becomes more complex if there are nested outer joins or the join condition does not consist entirely of equality comparisons.如果存在嵌套的外部联接或联接条件不完全由相等比较组成,则函数依赖性的确定将变得更加复杂。
Suppose that a view on countries produces their code, their name in uppercase, and how many different official languages they have:假设一个国家的观点产生了他们的代码,他们的名字是大写的,他们有多少种不同的官方语言:
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;
This definition is valid because:此定义有效,因为:
{co.Code} -> {co.*}
In the view result, the first selected column is 在视图结果中,第一个选定的列是co.Code
, which is also the group column and thus determines all other selected expressions:co.Code
,它也是成组列,因此确定所有其他选定表达式:
{country2.Code} -> {country2.*}
MySQL understands this and uses this information, as described following.MySQL理解并使用这些信息,如下所述。
This query displays countries, how many different official languages they have, and how many cities they have, by joining the view with the 此查询通过将视图与city
table: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;
This query is valid because, as seen previously:此查询有效,因为如前所述:
{co2.Code} -> {co2.*}
MySQL is able to discover a functional dependency in the result of a view and use that to validate a query which uses the view. MySQL能够发现视图结果中的函数依赖关系,并使用它来验证使用该视图的查询。The same would be true if 如果country2
were a derived table (or common table expression), as in: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;