2011-05-18 82 views
6

我读关于自然的简写形式SQL连接,我看到一些陷阱:NATURAL(JOIN)在生产环境中是否有害?

  • 它只是自动进行所有同名列对(使用通过指定明确的列清单)
  • 如果一些新列添加,然后再加入输出可以是“意外”变化太大,这可能是不那么明显(即使你知道如何自然科学作品)在复杂的结构

回答

11

NATURAL JOIN语法是反模式:

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

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

+2

查询的+1不太明显。阅读比写作难得多。 “ – 2011-05-18 04:52:44

+0

”语法违反模块化规则“ - 我认为你可以用这个语言对整个SQL语言进行收费。但是,如果您尽可能地遵守关系原则来应对SQL的挑战,那么'NATURAL JOIN'就会发光。 – onedaywhen 2011-05-18 08:40:09

+0

@onedaywhen:整个SQL语言?问题不在于关系原则 - 而在于生产级代码考虑。对我而言,这意味着:维护性,可读性,一致性和性能。很明显,你没有理由*创造一个*来证明downvoting。 – 2011-05-18 14:48:21

7

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

当表的语义暗示这是正确的事情时,使用NATURAL连接。无论表定义如何演变,如果要确保以特定方式完成连接,请使用显式连接标准。

+0

毫无疑问,NATURAL比严格的USING或一般的ON子句(这是为什么要避免它)有更多的“隐藏复杂”,但是如你所写,它依赖于语义。我想在大多数情况下,我想使用USING或ON,以确保具体的方式。 – 2011-05-18 05:02:44

+0

是的,我认为在大多数(但不是全部)情况下,明确表示更好。 – 2011-05-18 05:17:13

-1

你的意思是这样的语法:

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并获得巨大的结果集。我这样做是因为我容易出现拼写错误,这是我的保险。另外,它在视觉上更容易调试。

+0

不 - 第一个例子是ANSI-89语法,后者是ANSI-92。 'NATURAL JOIN'也是ANSI-92语法。特赦,我认为第一个是ANSI-89,但它是两个混合体,我怀疑除MySQL以外的其他任何软件都支持。 – 2011-05-18 04:13:31

+0

谢谢,但我的疑问是关于NATURAL(隐式“完整”列匹配列表)。我的意思是像SELECT * FROM t1 NATURAL LEFT JOIN t2; – 2011-05-18 04:20:44

+0

哦,有趣的是,我之前没有看到关键字NATURAL。对不起,浪费的答案,但谢谢你的新关键字。 – 2011-05-18 04:32:08

4

对我来说,完全破坏NATURAL的一件事是,我的大多数表格都有一个id列,它们在语义上显然是完全不同的。你可以争辩说,拥有user_idid更有意义,但是最终你会写出类似user.user_id的内容,这违反了DRY。此外,通过相同的逻辑,你也可以有像user_first_name,user_last_name,user_age这样的列(这也是有意义的,因为它会与例如session_age不同)......恐怖。

我会坚持我的JOIN ... ON ...,thankyouverymuch。 :)

3

我同意其他海报明确加入应该使用的清晰的原因,也容易切换到“外部”加入,如果您的要求改变。

但是,大多数“陷阱”与连接无关,而是使用“SELECT *”而不是明确命名所需列的弊端“SELECT a.col1,a.col2,b.col1,b .col2" 。无论何时使用通配符列表,都会发生这些陷阱。

1

添加未在上述任何答案中列出的额外原因。在使用NATURAL JOIN时,在postgres(不知道是否这是其他数据库的情况下)如果两个表之间没有共同的列名,那么执行CROSS JOIN。这意味着如果你有一个现有的查询,然后你随后改变一个表中的某个列名,你仍然会得到一组从查询返回的行而不是一个错误。如果您使用了JOIN ... USING(...)语法,则如果加入列不在那里,您将会收到错误。

postgres documentation has a note这个效果:

注意:使用是由所加入的关系柱变化相当安全的,因为只有列出的列组合。自然风险更大,因为任何模式更改为任何导致新匹配列名存在的关系都会导致连接将新列组合起来。