在SQL或MySQL中不使用JOIN关键字的连接有什么问题吗?

当我开始编写数据库查询时,我并不知道JOIN关键字,当然我只是扩展了我已经知道的内容,并写下如下的查询:

SELECT a.someRow, b.someRow FROM tableA AS a, tableB AS b WHERE a.ID=b.ID AND b.ID= $someVar 

现在我知道这和INNER JOIN是一样的,我在代码中查找所有这些查询,并问我自己是否应该重写它们。 有臭味吗?或者他们好吗?


编辑:

我的回答总结 :这个查询没有错,但使用关键字将最有可能使代码更易读/维护。

我的结论是 :我不会改变我的旧查询,但我会改正我的写作风格,并在将来使用关键字。

感谢您的答案!

在一些常见情况下,仅使用WHERE进行过滤连接可能效率极低。 例如:

 SELECT * FROM people p, companies c WHERE p.companyID = c.id AND p.firstName = 'Daniel' 

大多数数据库都会直接执行这个查询,首先将人和companies表的笛卡尔乘积进行过滤, 然后再进行匹配的companyID idid字段的过滤。 虽然完全不受约束的产品不存在于存储器中的任何地方,而只存在一段时间,但其计算确实需要一些时间。

更好的方法是将约束与JOIN进行分组。 这不仅在主观上更容易阅读,而且更有效率。 正是如此:

 SELECT * FROM people p JOIN companies c ON p.companyID = c.id WHERE p.firstName = 'Daniel' 

它稍微长一些,但数据库能够查看ON子句,并使用它来直接计算完全约束的JOIN ,而不是从一切开始,然后进行限制。 计算速度更快(特别是对于大数据集和/或多表连接)并且需要更less的内存。

我更改了每个使用“逗号JOIN ”语法的查询。 我认为,其存在的唯一目的是简洁。 考虑到性能的影响,我不认为这是一个令人信服的理由。

更加详细的INNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOIN是来自ANSI SQL / 92语法的join。 对我而言,这种冗长的特性使得开发人员/ DBA更加清楚了连接的意图。

在SQL Server中总是有查询计划来检查,文本输出可以如下进行:

 SET SHOWPLAN_ALL ON GO DECLARE @TABLE_A TABLE ( ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, Data VARCHAR(10) NOT NULL ) INSERT INTO @TABLE_A SELECT 'ABC' UNION SELECT 'DEF' UNION SELECT 'GHI' UNION SELECT 'JKL' DECLARE @TABLE_B TABLE ( ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY, Data VARCHAR(10) NOT NULL ) INSERT INTO @TABLE_B SELECT 'ABC' UNION SELECT 'DEF' UNION SELECT 'GHI' UNION SELECT 'JKL' SELECT A.Data, B.Data FROM @TABLE_A AS A, @TABLE_B AS B WHERE A.ID = B.ID SELECT A.Data, B.Data FROM @TABLE_A AS A INNER JOIN @TABLE_B AS B ON A.ID = B.ID 

现在我将省略tablevariablescreate的计划,两个查询的计划是相同的:

  SELECT A.Data, B.Data FROM @TABLE_A AS A, @TABLE_B AS B WHERE A.ID = B.ID |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID])) |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A])) |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD) SELECT A.Data, B.Data FROM @TABLE_A AS A INNER JOIN @TABLE_B AS B ON A.ID = B.ID |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID])) |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A])) |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD) 

所以,简短的回答 – 没有必要重写,除非你花费很长时间试图阅读他们每次你维护他们?

这是更多的语法select。 我更喜欢用我的连接分组我的连接条件,因此我使用INNER JOIN语法

 SELECT a.someRow, b.someRow FROM tableA AS a INNER JOIN tableB AS b ON a.ID = b.ID WHERE b.ID = ? 

(?是一个占位符)

在你的例子中没有什么是错误的语法。 “INNER JOIN”语法通常被称为“ANSI”语法,并且遵循示例中所示的样式。 它的存在是为了明确join的types/方向/组成部分,但通常在function上与你所拥有的不同。

对“ANSI”连接的支持是每个数据库平台,但现在它或多或less是普遍的。

作为一个侧面说明,“ANSI”语法的一个补充是“全外连接”或“全连接”。

希望这可以帮助。

一般来说:

使用JOIN关键字链接(即“join”)主键和外键。

使用WHERE子句将结果集仅限于您感兴趣的logging。

可能出现的一个问题是,当您尝试在同一查询中混合旧的“逗号样式”连接和SQL-92连接时,例如,如果您需要一个内连接和另一个外连接。

 SELECT * FROM table1 AS a, table2 AS b LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1 WHERE a.column2 = b.column2; 

问题是,最近的SQL标准认为JOIN在逗号join之前被评估。 所以在ON子句中对“a”的引用会给出一个错误,因为相关名字还没有被定义,因为ON子句正在被计算。 这是一个非常混乱的错误得到。

解决scheme是不混合两种风格的联接。 您可以在旧代码中继续使用逗号式样,但如果您编写新查询,请将所有连接转换为SQL-92样式。

 SELECT * FROM table1 AS a INNER JOIN table2 AS b ON a.column2 = b.column2 LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1; 

我避免隐式连接; 当查询真的很大时,他们会使代码很难破译

通过明确的连接和良好的格式化,代码更易读,易于理解,无需评论。

在旧的连接语法中要考虑的另一件事情是,由于没有on子句,因此很容易意外地获得cartesion连接。 如果Distinct关键字在查询中,并且它使用旧式联接,则将其转换为ANSI标准联接,并查看是否仍然需要该联结。 如果您正在修复意外的cartesion连接,您可以通过重写指定连接和连接字段来极大地提高性能。

这也取决于你是否只是这样做内部连接或外部连接。 例如,用于WHERE子句(= *和* =)中的外连接的MS SQL Server语法可以给出与OUTER JOIN语法不同的结果,并且不再支持( http://msdn.microsoft.com/zh-cn/library/default.mspx); /library/ms178653(SQL.90).aspx )在SQL Server 2005中。