Соединения SQL: будущее стандарта SQL ANSI (где и соединение)?

Мы разрабатываем задания ETL, и наш консультант использует SQL «старого стиля» при объединении таблиц.

select a.attr1, b.attr1
from table1 a, table2 b
where a.attr2 = b.attr2

вместо использования предложения внутреннего соединения

select a.attr1, b.attr1
from table1 as a inner join table2 as b
   on a.attr2 = b.attr2

Мой вопрос в том, что в долгосрочной перспективе есть ли риск использования старого «где присоединиться»? Как долго такие соединения поддерживаются и сохраняются в качестве стандарта ANSI? Нашей платформой является SQL Server, и моя основная причина заключается в том, что в будущем эти «соединения» больше не поддерживаются. Когда это происходит, мы должны изменить все наши задания ETL, используя стиль соединений «внутреннее соединение».


person atricapilla    schedule 10.09.2010    source источник


Ответы (9)


Я сомневаюсь, что «где присоединяется» никогда не будет поддерживаться. Не поддерживать их просто невозможно, потому что они основаны на декартовых произведениях и простой фильтрации. На самом деле они не являются соединениями.

Но есть много причин использовать новый синтаксис соединения. Среди прочего:

  • Читабельность
  • Ремонтопригодность
  • Более легкий переход на внешние соединения
person Stefan Steinegger    schedule 10.09.2010

Вместо того, чтобы беспокоиться о каком-то возможном риске в будущем, почему бы не беспокоиться о риске, с которым вы сталкиваетесь прямо сейчас?

В дополнение к пунктам Марка:

  • Код труднее читать (и, следовательно, понимать его назначение), когда предложения ON отсоединены (иногда на много строк) от соединяемых таблиц. Это увеличивает вероятность ошибок при модификации кода.
  • Определить, какой тип JOIN выполняется, сложнее — вам нужно просмотреть предложение WHERE и надеяться, что то, что вы видите, верно.
  • Найти отсутствующие предложения JOIN намного сложнее, что увеличивает риск непреднамеренного декартова соединения — при использовании синтаксиса ANSI предложения ON хорошо выстраиваются, что делает эту задачу тривиальной.
person D'Arcy Rittich    schedule 10.09.2010

Есть много причин избегать неявных соединений. Большие из них:

  • Его нельзя легко изменить на внешнее соединение.
  • С неявным соединением проще забыть условие соединения.
  • Если вы смешиваете как неявные, так и явные соединения, вы получаете проблемы с запутанным приоритетом. Вот пример, сделанный несколько часов назад: Синтаксическая ошибка MySQL.

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

person Mark Byers    schedule 10.09.2010

Оба синтаксиса поддерживаются последними версиями ISO SQL (2003, 2008). Использование запятых для указания перекрестного соединения в предложении FROM является совершенно стандартным SQL и поддерживается всеми продуктами SQL, с которыми я сталкивался. Кажется крайне маловероятным, что он когда-либо будет или даже может быть объявлен устаревшим или прекращенным в SQL.

person nvogel    schedule 10.09.2010

Пока они не используют ***= и =* для своего синтаксиса соединения (который был устарел в SQL Server 2008 R2), я не думаю, что он исчезнет в долгосрочной перспективе, но, как говорит Марк Байерс, есть много причин не делать этого.

Больше всего меня беспокоит то, что если они пишут такие соединения, что еще они делают нестандартного?

person LittleBobbyTables - Au Revoir    schedule 10.09.2010

У людей было несколько хороших моментов, но пока есть два важных, которые не были упомянуты:

  1. Независимо от того, давали ли внешние соединения *= и =* в старом стиле правильные результаты, они также не могут правильно обозначать определенные соединения. Рассмотрим следующий запрос. Мы хотим показать всем клиентам, которые не разместили заказ на сумму более 100 долларов США:

    SELECT
    FROM
       Customer C
       LEFT JOIN Order O ON C.OrderID = O.OrderID AND O.OrderTotal >= 100.0;
    WHERE
       O.OrderID IS NULL;
    

    Попробуйте выразить это по-старому... если сможете. Без использования производных таблиц.

  2. Для меня большая ценность использования правильных предложений соединения заключается в отделении стандартных условий соединения (которые будут применяться почти в каждом запросе, включающем эти две таблицы) от специальных фильтров для этого запроса, которые будут возвращать желаемое ряды:

    SELECT
       C.FullName,
       C.CustomerCode,
       O.OrderDate,
       O.OrderTotal,
       OD.ExtendedShippingNotes
    FROM
       Customer C
       INNER JOIN Order O ON C.CustomerID = O.CustomerID
       INNER JOIN OrderDetail OD ON O.OrderID = OD.OrderID
    WHERE
       C.CustomerStatus = 'Preferred'
       AND O.OrderTotal > 1000.0;
    

    Это разделение означает, что разработчику, просматривающему запрос, не приходится иметь дело с кучей беспорядка при поиске отличительных особенностей этого запроса. Если он знаком с таблицами, он может полностью пропустить предложение FROM и просто прочитать предложение WHERE, чтобы получить всю необходимую ему информацию. Это быстрее. И если вам наплевать на скорость, даже при простом сканировании запросов глазами, я не хочу с вами работать.

    Теперь для тех, кто думает, что есть что-то особенное в расположении всего при использовании синтаксиса JOIN, вы ошибаетесь. Следующий запрос работает так же хорошо, как и предыдущий:

    SELECT
       C.FullName,
       C.CustomerCode,
       O.OrderDate,
       O.OrderTotal,
       OD.ExtendedShippingNotes
    FROM
       Customer C
       CROSS JOIN Order O
       INNER JOIN OrderDetail OD
          ON C.CustomerID = O.CustomerID
          AND C.CustomerStatus = 'Preferred'
          AND O.OrderTotal > 1000.0
    WHERE
       O.OrderID = OD.OrderID;
    

    Этот запрос, вероятно, даже имеет точно такой же план выполнения. Удивлен? Не будь. Как и в случае с синтаксисом в старом стиле, именно оптимизатор отвечает за выяснение того, как соединить ваши таблицы на основе заданных вами условий. На самом деле не имеет значения, где находятся условия, пока они не относятся к таблице, которая еще не упоминалась.

Так в чем же большая разница между двумя стилями? Если вы думаете, что второй запутанный запрос сложно понять и написать его было бы безумием, то вы, естественно, думаете, что старый стиль запроса неубедителен. Потому что, откровенно говоря, бессистемно помещать все условия в какое-то старое место неорганизованно. Система организации JOIN имеет смысл. Если вы привыкли к старому стилю и не очень любите новый стиль, то это, наверное, потому, что перемены неприятны (для всех нас). Но как только вы попользуетесь им какое-то время, я уверен, что он вам понравится. По крайней мере, если это не так, я не могу понять, почему.

person ErikE    schedule 11.09.2010
comment
Я бы перевернул ваш аргумент с ног на голову. Итак, ANSI предоставляет вам способ лучше структурировать ваш запрос, но не имеет возможности обеспечить его соблюдение? Могу поспорить, что некоторые разработчики воспользуются этим, создав беспорядок (собственно, именно поэтому я здесь). Что касается внешних объединений, то здесь аргументов нет — это соединение не является ассоциативным, по крайней мере, вы должны поставить круглые скобки, чтобы устранить неоднозначность вложенности. ANSI должен был просто исправить внешнее соединение и оставить декартовы производные соединения в покое. - person Tegiri Nenashi; 02.03.2011
comment
@Tegiri Прошу прощения, я не совсем понимаю, о чем вы говорите. Ни в старом стиле, ни в стиле ANSI ничего не навязывается. Так что там нет проблем. И вы все еще можете использовать скобки, если хотите. Или вы можете просто перемещать предложения ON, чтобы имитировать круглые скобки и обеспечить порядок соединения (и нет двусмысленности). Кроме того, вы можете получать декартовы произведения сколько угодно с помощью CROSS JOIN или даже INNER JOIN ON 1 = 1. Насколько вы опытны с соединениями ANSI? - person ErikE; 03.03.2011

Трудно спорить об изяществе или безобразии той или иной синтаксической конструкции. Вы просто видите это или нет. Синтаксис соединения, разделенного запятыми, отражает фундаментальную особенность реляционной алгебры, которая утверждает нормальную форму для запросов выбора-проекта-соединения. Единственный тип соединения, который его избегает (и, следовательно, требует специального синтаксиса), — это внешнее соединение. Случайные ошибки отсутствия предикатов равенства, из-за которых граф соединения становится непересекающимся, — это всего лишь вопрос сложности вашего внешнего инструмента программирования SQL (отображает ли он граф соединения вообще?).

Это не только эстетика. В рабочих базах данных обычно есть такие столбцы, как CREATED_ON или COMMENTS, во многих таблицах. В этом случае синтаксис NATURAL JOIN просто опасен.

Как красноречиво выразился Энтони Молинаро (автор популярной «Поваренной книги SQL»): «Старый стиль краток, мил и совершенен. ANSI упростил его, и для людей, которые какое-то время занимались разработкой, это совершенно не нужно".

person Tegiri Nenashi    schedule 10.09.2010
comment
Я действительно не понимаю, как одни и те же условия, просто расположенные в другом месте, отупляют. А благодаря новым расширениям SQL Server CROSS APPLY и OUTER APPLY можно сделать еще больше, чего нельзя было сделать с помощью соединений в старом стиле. Я боюсь сказать, что аргумент здесь просто звучит как динозавр, держащийся за свою каменную дубину (хотя вам больше силы, если вам это нравится). Только не называй это глупым, когда это не так! Кроме того, я не вижу новой опасности в столбцах, общих для многих таблиц. Если вы не используете псевдонимы, у вас в любом случае проблемы. - person ErikE; 04.03.2011

Подразумеваемый синтаксис правого и левого соединения *= и =* устарел и по уважительной причине в настоящее время не всегда возвращает правильные результаты. Если они использовали это, они ДОЛЖНЫ быть исправлены сейчас, поскольку в настоящее время они подвергают вас риску получения неверных результатов. Это не вариант. Другой синтаксис будет продолжать работать, но его также следует заменить по нескольким причинам. Во-первых, очень легко получить случайные перекрестные соединения, которые могут возвращать плохие результаты или которые исправляются с помощью различных, что может создать проблемы с производительностью.

Другой вопрос - техническое обслуживание. Если позже люди добавят в запрос другие соединения и снова начнут смешивать подразумеваемые и явные соединения, вы можете получить неправильные результаты и даже не знать об этом. ОЧЕНЬ ОЧЕНЬ плохо оставлять такой дрянной код в своей кодовой базе. Подразумеваемые соединения также труднее понять, и, поскольку они часто пишутся разработчиками, которые ничего не понимают в соединениях, они в любом случае могут оказаться не тем, что вам нужно. И если в запросе есть перекрестное соединение, как сопровождающему узнать, было ли это ошибкой (и случайным перекрестным соединением) или преднамеренным перекрестным соединением (иногда они нам действительно нужны). Я бы не принял этот код в том виде, в котором он написан. Я бы настаивал на том, чтобы некомпетентные авторы исправили это без дополнительной оплаты.

person HLGEM    schedule 10.09.2010

Если вы беспокоитесь, что они будут удалены из Стандарта или из продуктов SQL, не волнуйтесь. Это вряд ли когда-либо произойдет.

Этот «старый стиль» соединения — это просто вопрос стиля. Те, кто одобряет его, клянутся, что есть ситуации, когда соединения «старого стиля» легче понять. Хотя я сам не совсем в этом уверен, одно можно сказать наверняка: соединения старого стиля будут время от времени встречаться, а реинжиниринг кода в соответствии с вашим личным стилем не всегда уместен. Поэтому привыкайте к стилю и учитесь с ним работать.

person onedaywhen    schedule 10.09.2010
comment
Нет, это не просто вопрос стиля, существуют очень серьезные проблемы с использованием такого соединения. - person HLGEM; 10.09.2010
comment
@HLGEM - вы говорите это только потому, что это не в вашем вкусе. - person onedaywhen; 10.09.2010
comment
Np Я говорю это, потому что это приводит к неправильным результатам запросов и проблемам с обслуживанием. - person HLGEM; 10.09.2010
comment
@HLGEM - нет, если вы привыкли к этому стилю. Я ценю то, что вы говорите, но «старый стиль» более распространен, чем вы, возможно, думаете. Вы можете попробовать, но вы не избавите мир от этого. Лучше смириться с этим :) - person onedaywhen; 10.09.2010
comment
Тот факт, что что-то является общим, не является оправданием для использования этого в новой разработке, когда это рискованно. Нет причин КОГДА-ЛИБО использовать этот синтаксис, который устарел на 18 лет, и если вы поддерживаете фрагмент кода, который его использует, нет никаких оправданий, чтобы не исправить его, как если бы вы исправили плохой код C #, используя устаревший метод. который был заменен 8 лет назад чем-то менее рискованным. Это плохой синтаксис, нет оправдания его использованию. - person HLGEM; 10.09.2010
comment
@HLGEM: нет причин КОГДА-ЛИБО использовать этот синтаксис - есть, если вы используете базу данных (например, Oracle до версии 9), которая не поддерживает синтаксис JOIN. Не применимо в этом случае, но во многих других. - person ; 10.09.2010
comment
@HLGEM: что вы имеете в виду под неправильными результатами запроса? Вы имеете в виду, что, по вашему мнению, разработчик с меньшей вероятностью допустит ошибки при использовании предложения ON, чем при использовании тех же выражений в предложении WHERE? - person nvogel; 10.09.2010
comment
Подразумеваемый синтаксис правого и левого соединения даже в SQL Server 2000 иногда дает неправильные результаты, поскольку он не всегда интерпретируется как правильное внешнее соединение. Случайные перекрестные соединения невозможны с явным синтаксисом соединения, и, таким образом, подразумеваемый синтаксис может возвращать набор результатов, который неверен, но не кажется разработчику неправильным. Запросы со смесью явных и неявных соединений могут быть неправильно интерпретированы оптимизатором и возвращать неверные результаты. Вот почему старый синтаксис опасен и не должен использоваться. - person HLGEM; 10.09.2010
comment
@HLGEM: синтаксис соединения через запятую является такой же частью текущего стандарта SQL, как и предложение JOIN. Это не старо. Соединение через запятую на самом деле является более общим, чем ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Не все соединения через запятую можно сократить до ВНУТРЕННИХ СОЕДИНЕНИЙ, потому что запятая эквивалентна ПЕРЕКРЕСТНОМУ СОЕДИНЕНИЮ в SQL. Ваши комментарии о левом и правом не применяются, если вы не используете операторы соединения слева направо (я согласен, что для этого вам следует использовать синтаксис OUTER JOIN, но здесь это не обсуждается). Больше людей знакомы с синтаксисом запятой, и он совместим с большим количеством программ. Это, по крайней мере, несколько веских причин для его использования. - person nvogel; 10.09.2010
comment
Соединение через запятую на самом деле является более общим, чем ВНУТРЕННЕЕ СОЕДИНЕНИЕ. Не все соединения через запятую можно сократить до ВНУТРЕННИХ СОЕДИНЕНИЙ, потому что запятая эквивалентна ПЕРЕКРЕСТНОМУ СОЕДИНЕНИЮ в SQL. Именно поэтому его не следует использовать. Это устаревший, рискованный код. - person HLGEM; 10.09.2010
comment
Под рискованным я предполагаю, что вы имеете в виду более читаемый и ясный, что происходит. Однако это очень субъективная оценка. Я хорошо разбираюсь в обоих синтаксисах, но я видел примеры, в которых я обнаружил, что использование смешанной комбинации предложений INNER JOIN / CROSS JOIN и ON вместо одного предложения WHERE затрудняет понимание того, что означает запрос. Оба синтаксиса допустимы. Используйте то, что делает намерение более ясным. - person nvogel; 10.09.2010