旧的语法,只是列出表,并使用WHERE 子句来指定连接条件,在大多数现代数据库中已被弃用。
这不仅仅是为了展示,当您在同一查询中同时使用 INNER 和 OUTER 联接时,旧语法可能会产生歧义。
让我举个例子。
假设您的系统中有 3 个表:
Company
Department
Employee
每个表都包含许多行,它们链接在一起。你有多个公司,每个公司可以有多个部门,每个部门可以有多个员工。
好的,现在您要执行以下操作:
列出所有公司,并包括其所有部门和所有员工。请注意,有些公司还没有任何部门,但请确保您也将它们包括在内。确保只检索有员工的部门,但始终列出所有公司。
所以你这样做:
SELECT * -- for simplicity
FROM Company, Department, Employee
WHERE Company.ID *= Department.CompanyID
AND Department.ID = Employee.DepartmentID
请注意,最后一个是内部联接,以满足您只希望部门中有人员的条件。
好的,那么现在会发生什么。好吧,问题是,它取决于数据库引擎、查询优化器、索引和表统计信息。让我解释一下。
如果查询优化器确定这样做的方法是先获取公司,然后找到部门,然后与员工进行内部联接,那么您将不会得到任何没有部门的公司.
原因是WHERE 子句确定最终结果中的行,而不是行的各个部分。
在这种情况下,由于左连接,Department.ID 列将为 NULL,因此当涉及到 Employee 的 INNER JOIN 时,没有办法满足 Employee 行的约束,所以它不会出现。
另一方面,如果查询优化器决定先处理部门-员工联接,然后与公司进行左联接,您将看到它们。
所以旧的语法是模棱两可的。没有办法指定你想要什么,不处理查询提示,有些数据库根本没有办法。
输入新的语法,你可以选择。
例如,如果您想要所有公司,如问题描述所述,您会这样写:
SELECT *
FROM Company
LEFT JOIN (
Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
) ON Company.ID = Department.CompanyID
您在此处指定您希望将部门-员工联接作为一个联接完成,然后将结果与公司左侧联接。
此外,假设您只需要名称中包含字母 X 的部门。同样,使用旧式联接,您也有失去公司的风险,如果它没有任何名称中带有 X 的部门,但使用新语法,您可以这样做:
SELECT *
FROM Company
LEFT JOIN (
Department INNER JOIN Employee ON Department.ID = Employee.DepartmentID
) ON Company.ID = Department.CompanyID AND Department.Name LIKE '%X%'
这个额外的子句用于连接,但不是整行的过滤器。因此,该行可能会显示公司信息,但可能在该行的所有部门和员工列中都有 NULL,因为该公司的名称中没有带有 X 的部门。旧语法很难做到这一点。
这就是为什么在其他供应商中,自 SQL Server 2005 及更高版本以来,Microsoft 已弃用旧的外连接语法,而不是旧的内连接语法。使用旧式外连接语法与运行在 Microsoft SQL Server 2005 或 2008 上的数据库通信的唯一方法是将该数据库设置为 8.0 兼容模式(也称为 SQL Server 2000)。
此外,通过向查询优化器抛出一堆表和一堆 WHERE 子句,旧方法类似于说“你在这里,尽你所能”。使用新语法,查询优化器只需要做更少的工作来确定哪些部分组合在一起。
所以你有它。
LEFT and INNER JOIN 是未来的潮流。