10

我正在阅读有关 SQL 连接的 NATURAL 速记形式的信息,我看到了一些陷阱:

  • 它只是自动使用所有相同的命名列对(使用 USING 指定显式列列表)
  • 如果添加了一些新列,则连接输出也可能“意外”更改,这在复杂结构中可能不那么明显(即使您知道 NATURAL 是如何工作的)
4

6 回答 6

20

NATURAL JOIN语法是反模式:

  • 查询的目的不太明显;
    • 应用程序使用的列不明确
    • 使用的列可以“意外”改变
  • 该语法违反了模块化规则,即尽可能使用严​​格类型。显式几乎普遍更好。

因此,我不建议在任何环境中使用该语法。
我也不推荐混合语法(即:同时使用NATURAL JOIN和显式的 INNER/OUTER JOIN 语法)——保持一致的代码库格式。

于 2011-05-18T04:07:44.830 回答
7

这些似乎反对自然连接的“陷阱”是双向的。假设您在表 A 中添加一个新列,并完全期望它用于与表 B 连接。如果您知道 A 和 B 的每个连接都是自然连接,那么您就完成了。如果每个连接都明确使用 USING,那么您必须全部跟踪并更改它们。错过一个,有一个错误。

当表的语义表明这是正确的做法时,请使用 NATURAL 联接。当您想确保以特定方式完成连接时,请使用显式连接条件,而不管表定义如何演变。

于 2011-05-18T04:06:57.710 回答
5

对我来说完全破坏的一件事是NATURAL我的大多数表都有一个id列,这些列显然在语义上都是不同的。您可能会争辩说 auser_id比 更有意义id,但是您最终会写出诸如user.user_id违反 DRY 之类的东西。此外,按照相同的逻辑,您还会有类似user_first_name, user_last_name, user_age... 的列(考虑到它与例如 , 不同,这也是有道理的session_age)... 恐怖。

我会坚持我的JOIN ... ON ...,非常感谢。:)

于 2011-05-18T04:12:36.160 回答
3

我同意其他发帖者的观点,即为了清楚起见,应该使用显式连接,并且如果您的要求发生变化,也可以轻松地切换到“外部”连接。

但是,您的大多数“陷阱”与连接无关,而是使用“SELECT *”而不是显式命名您需要“SELECT a.col1、a.col2、b.col1、b.col2”的列的弊端。只要使用通配符列列表,就会出现这些陷阱。

于 2011-05-18T04:15:58.170 回答
2

添加上述任何答案中未列出的额外原因。在 postgres 中(不确定其他数据库是否是这种情况)如果在使用时在两个表之间没有找到共同的列名,则执行NATURAL JOINa CROSS JOIN。这意味着,如果您有一个现有的查询,然后您随后更改了表中的一个列名,您仍然会从查询中返回一组行,而不是错误。相反,如果您使用该JOIN ... USING(...)语法,如果连接列不再存在,您将收到错误消息。

postgres 文档对此有注释

注意: USING 对于连接关系中的列更改是相当安全的,因为仅组合了列出的列。NATURAL 的风险要大得多,因为对任一关系的任何模式更改都会导致出现新的匹配列名称,这也会导致连接合并该新列。

于 2016-10-27T17:21:20.817 回答
-2

你的意思是这样的语法:

SELECT * 
  FROM t1, t2, t3 ON t1.id = t2.id 
                 AND t2.id = t3.id

与此相反:

         SELECT *  
           FROM t1 
LEFT OUTER JOIN t2 ON t1.id = t2.id 
                  AND t2.id = t3.id

我更喜欢第二种语法,并且格式也不同:

         SELECT *
           FROM T1
LEFT OUTER JOIN T2 ON T2.id = T1.id
LEFT OUTER JOIN T3 ON T3.id = T2.id

在这种情况下,很清楚我要加入哪些表以及我使用什么 ON 子句来加入它们。通过使用第一个语法太容易了,无法放入正确的 JOIN 并获得巨大的结果集。我这样做是因为我容易出现拼写错误,这是我的保险。另外,它在视觉上更容易调试。

于 2011-05-18T04:10:54.347 回答