我正在阅读关于SQL连接的NATURAL简写形式,我看到了一些陷阱:
答案 0 :(得分:15)
NATURAL JOIN
语法是反模式的:
因此,我不建议在任何环境中使用语法
我也不建议混合语法(IE:同时使用NATURAL JOIN
和显式的INNER / OUTER JOIN语法) - 保持一致的代码库格式。
答案 1 :(得分:7)
这些似乎反对自然联合的“陷阱”切断了两种方式。假设你向表A添加一个新列,完全期望它用于加入表B.如果你知道A和B的每个连接都是一个自然连接,那么你就完成了。如果每个连接明确使用USING,那么您必须全部跟踪它们并更改它们。小姐一个,而且有一个错误。
当表的语义表明这是正确的事情时,使用NATURAL连接。如果要确保以特定方式完成连接,请使用显式连接条件,而不管表定义如何演变。
答案 2 :(得分:4)
对我来说完全破坏NATURAL
的一件事是我的大多数表都有一个id
列,它们在语义上显然都是不同的。你可以说,user_id
比id
更有意义,但最后你会写user.user_id
之类的东西,这违反了DRY。此外,按照相同的逻辑,您还可以使用user_first_name
,user_last_name
,user_age
等列...(鉴于它与以下内容不同,这也是有意义的,因为例如,session_age
)......恐怖。
我会坚持我的JOIN ... ON ...
,而不是很多。 :)
答案 3 :(得分:3)
我同意其他海报,为了清楚起见,应该使用显式连接,并且如果您的要求发生变化,也可以轻松地切换到“OUTER”连接。
然而,大多数“陷阱”与连接无关,而是使用“SELECT *”而不是显式命名所需列的邪恶“SELECT a.col1,a.col2,b.col1,b。 COL2" 。只要使用通配符列列表,就会发生这些陷阱。
答案 4 :(得分:1)
添加上述任何答案中未列出的额外原因。在postgres中(不确定是否为其他数据库的情况)如果在使用NATURAL JOIN
时两个表之间没有共同的列名,则执行CROSS JOIN
。这意味着如果您有一个现有查询,然后您随后要更改表中的一个列名,您仍然会获得从查询返回的一组行而不是错误。如果使用JOIN ... USING(...)
语法,如果加入列不再存在,则会出现错误。
这个效果的postgres documentation has a note:
注意:USING对连接关系中的列更改是相当安全的,因为只组合列出的列。自然风险要大得多,因为任何模式更改为导致新匹配列名称存在的任一关系都将导致联接也组合该新列。
答案 5 :(得分:-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并得到一个巨大的结果集。我这样做是因为我容易发生错别字,这是我对此的保险。此外,它在视觉上更容易调试。