Считается ли NATURAL (JOIN) вредным в производственной среде? - PullRequest
7 голосов
/ 18 мая 2011

Я читаю о НАТУРАЛЬНОЙ сокращенной форме для соединений SQL и вижу некоторые ловушки:

  • он просто принимает автоматически все пары столбцов с одинаковыми именами (используйте USING для указания явного списка столбцов)
  • если добавлен какой-то новый столбец, то выходные данные объединения также могут быть «неожиданно» изменены, что может быть не так очевидно (даже если вы знаете, как работает NATURAL) в сложных структурах

Ответы [ 6 ]

15 голосов
/ 18 мая 2011

NATURAL JOIN синтаксис является анти-паттерном:

  • Цель запроса менее очевидна;
    • столбцы, используемые приложением, не ясны
    • используемые столбцы могут изменяться «неожиданно»
  • Синтаксис: против правила модульности , об использовании строгой типизации, когда это возможно.Явное почти всегда лучше.

Из-за этого я не рекомендую синтаксис в любой среде.
Я также не рекомендую смешивать синтаксис (т. Е. Использовать как NATURAL JOIN, так и явный синтаксис INNER / OUTER JOIN) - поддерживать постоянный формат кодовой базы.

7 голосов
/ 18 мая 2011

Эти «ловушки», которые, похоже, противоречат естественным соединениям, прорезают оба пути. Предположим, вы добавили новый столбец в таблицу A, полностью ожидая, что он будет использован при объединении с таблицей B. Если вы знаете, что каждое объединение A и B является естественным объединением, то все готово. Если каждое объединение явно использует USING, то вы должны отследить их все и изменить. Пропусти один и есть ошибка.

Используйте НАТУРАЛЬНЫЕ объединения, когда семантика таблиц предполагает, что это правильно. Используйте явные критерии объединения, когда хотите убедиться, что соединение выполнено определенным образом, независимо от того, как могут развиваться определения таблиц.

4 голосов
/ 18 мая 2011

Одна вещь, которая полностью разрушает NATURAL для меня, состоит в том, что большинство моих таблиц имеют столбец id, который, очевидно, семантически все различен.Вы можете утверждать, что наличие user_id имеет больше смысла, чем id, но тогда вы в конечном итоге пишете такие вещи, как user.user_id, что является нарушением DRY.Кроме того, по той же логике у вас также могут быть столбцы типа user_first_name, user_last_name, user_age ... (что также имеет смысл, учитывая, что он будет отличаться, например, от session_age)... Ужас.

Я буду придерживаться моего JOIN ... ON ..., спасибо, очень много.:)

3 голосов
/ 18 мая 2011

Я согласен с другими авторами, что для ясности следует использовать явное объединение, а также для того, чтобы легко разрешить переход к объединению "ВНЕШНЕЕ" в случае изменения ваших требований.

Однако большинство ваших «ловушек» не имеют ничего общего с объединениями, а скорее со злом использования «SELECT *» вместо явного именования нужных вам столбцов «SELECT a.col1, a.col2, b.col1, b. col2" . Эти ловушки возникают всякий раз, когда используется список столбцов с подстановочными знаками.

1 голос
/ 27 октября 2016

Добавление дополнительной причины, не указанной ни в одном из ответов выше.В postgres (не уверен, что это так для других баз данных), если имена столбцов, общих для двух таблиц, при использовании NATURAL JOIN не найдены, тогда выполняется CROSS JOIN.Это означает, что если бы у вас был существующий запрос, а затем вы должны были впоследствии изменить одно из имен столбцов в таблице, вы все равно получили бы набор строк, возвращаемых из запроса, а не ошибку.Если вместо этого вы используете синтаксис JOIN ... USING(...), вы получите сообщение об ошибке, если объединяющего столбца больше нет.

В документации postgres есть примечание на этот счет:

Примечание: ИСПОЛЬЗОВАНИЕ достаточно безопасно от изменений столбцов в соединенных отношениях, поскольку объединяются только перечисленные столбцы.NATURAL значительно более рискован, поскольку любые изменения схемы в любом отношении, приводящие к появлению нового совпадающего имени столбца, приведут к объединению и этого нового столбца.

0 голосов
/ 18 мая 2011

Вы имеете в виду синтаксис, подобный следующему:

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 и получить огромный набор результатов.Я делаю это, потому что я склонен к опечаткам, и это моя страховка от этого.Кроме того, визуально легче отлаживать.

...