NATURAL(JOIN)在生产环境中是否被认为有害?

发布于 2024-11-08 06:56:39 字数 199 浏览 10 评论 0原文

我正在阅读有关 SQL 连接的 NATURAL 简写形式,我看到了一些陷阱:

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

I am reading about NATURAL shorthand form for SQL joins and I see some traps:

  • it just takes automatically all same named column-pairs (use USING to specify explicit column list)
  • if some new column is added, then join output can be "unexpectedly" changed too, which may be not so obvious (even if you know how NATURAL works) in complicated structures

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

念三年u 2024-11-15 06:56:39

NATURAL JOIN 语法是反模式:

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

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

NATURAL JOIN syntax is anti-pattern:

  • The purpose of the query is less obvious;
    • the columns used by the application is not clear
    • the columns used can change "unexpectedly"
  • The syntax goes against the modularity rule, about using strict typing whenever possible. Explicit is almost universally better.

Because of this, I don't recommend the syntax in any environment.
I also don't recommend mixing syntax (IE: using both NATURAL JOIN and explicit INNER/OUTER JOIN syntax) - keep a consistent codebase format.

美胚控场 2024-11-15 06:56:39

对我来说,完全破坏 NATURAL 的一件事是,我的大多数表都有一个 id 列,这些列在语义上显然是不同的。您可能会认为拥有 user_idid 更有意义,但最终您会编写诸如 user.user_id 之类的内容,这违反了 DRY 。此外,按照相同的逻辑,您还会有诸如 user_first_nameuser_last_nameuser_age... 之类的列(这在以下情况下也有意义)认为它与例如 session_age 不同)...恐怖。

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

One thing that completely destroys NATURAL for me is that most of my tables have an id column, which are obviously semantically all different. You could argue that having a user_id makes more sense than id, but then you end up writing things like user.user_id, a violation of DRY. Also, by the same logic, you would also have columns like user_first_name, user_last_name, user_age... (which also kind of makes sense in view that it would be different from, for example, session_age)... The horror.

I'll stick to my JOIN ... ON ..., thankyouverymuch. :)

鸠魁 2024-11-15 06:56:39

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

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

These "traps", which seem to argue against natural joins, cut both ways. Suppose you add a new column to table A, fully expecting it to be used in joining with table B. If you know that every join of A and B is a natural join, then you're done. If every join explicitly uses USING, then you have to track them all down and change them. Miss one and there's a bug.

Use NATURAL joins when the semantics of the tables suggests that this is the right thing to do. Use explicit join criteria when you want to make sure the join is done in a specific way, regardless of how the table definitions might evolve.

乖乖哒 2024-11-15 06:56:39

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

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

I agree with the other posters that an explicit join should be used for reasons of clarity and also to easily allow a switch to an "OUTER" join should your requirements change.

However most of your "traps" have nothing to do with joins but rather the evils of using "SELECT *" instead of explicitly naming the columns you require "SELECT a.col1, a.col2, b.col1, b.col2". These traps occurs whenever a wildcard column list is used.

笑,眼淚并存 2024-11-15 06:56:39

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

postgres 文档对此有注释

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

Adding an extra reason not listed in any of the answers above. In postgres (not sure if this the case for other databases) if no column names are found in common between the two tables when using NATURAL JOIN then a CROSS JOIN is performed. This means that if you had an existing query and then you were to subsequently change one of the column names in a table, you would still get a set of rows returned from the query rather than an error. If instead you used the JOIN ... USING(...) syntax you would get an error if the joining column was no longer there.

The postgres documentation has a note to this effect:

Note: USING is reasonably safe from column changes in the joined relations since only the listed columns are combined. NATURAL is considerably more risky since any schema changes to either relation that cause a new matching column name to be present will cause the join to combine that new column as well.

天生の放荡 2024-11-15 06:56:39

您的意思是这样的语法吗:

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

Do you mean the syntax like this:

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

Versus this:

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

I prefer the 2nd syntax and also format it differently:

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

In this case, it is very clear what tables I am joining and what ON clause I am using to join them. By using that first syntax is just too easy to not put in the proper JOIN and get a huge result set. I do this because I am prone to typos, and this is my insurance against that. Plus, it is visually easier to debug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文