Почему стандарт SQL ANSI-92 не лучше, чем ANSI-89?


в каждой компании, в которой я работал, я обнаружил, что люди все еще пишут свои SQL-запросы в стандарте ANSI-89:

select a.id, b.id, b.address_1
from person a, address b
where a.id = b.id

вместо стандарта ANSI-92:

select a.id, b.id, b.address_1
from person a
inner join address b
on a.id = b.id

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

когда я пытаюсь проповедовать ANSI-92 людям, есть ли какие-либо конкретные преимущества в использовании ANSI-92 над ANSI-89? Я бы попробовал это самостоятельно, но настройки Oracle, которые у нас есть здесь, не позволяют нам использовать EXPLAIN PLAN - не хотели бы, чтобы люди пытались оптимизировать свой код, не так ли?

16 97

16 ответов:

согласно "настройке производительности SQL" Питера Гулуцана и Труди Пельцер, из шести или восьми брендов СУБД, которые они тестировали, не было никакой разницы в оптимизации или производительности SQL-89 по сравнению с соединениями стиля SQL-92. Можно предположить, что большинство механизмов СУБД преобразуют синтаксис во внутреннее представление перед оптимизацией или выполнением запроса, поэтому удобочитаемый синтаксис не имеет никакого значения.

Я также пытаюсь евангелизировать синтаксис SQL-92. Шестнадцать лет спустя это было одобрено, это о времени люди начинают использовать его! И все бренды базы данных SQL теперь поддерживают его, поэтому нет причин продолжать использовать отвратительный (+) синтаксис Oracle или *= синтаксис Microsoft/Sybase.

Я постепенно вижу, что люди используют синтаксис SQL-92 чаще, чем раньше. Я отвечаю на вопросы SQL в интернете с 1994 года.

ну стандарт ANSI092 включает в себя довольно отвратительный синтаксис. Естественные Соединения - Это одно и то используя П. Это другое. ИМХО, добавление столбца в таблицу не должно нарушать код, но естественное соединение ломается самым вопиющим образом. "Лучший" способ сломать-это ошибка компиляции. Например, если вы выберете * где-то, добавление столбца может компилироваться. Следующий лучший способ потерпеть неудачу - это ошибка времени выполнения. Это хуже, потому что ваши пользователи может быть, вы и видите это, но это все равно дает вам хорошее предупреждение о том, что вы что-то сломали. Если вы используете ANSI92 и пишете запросы с естественными соединениями, он не сломается во время компиляции и не сломается во время выполнения, запрос просто внезапно начнет давать неправильные результаты. Эти типы ошибок коварны. Отчеты идут неправильно, потенциально раскрытие финансовой информации неверно.

для тех, кто не знаком с естественными соединениями. Они объединяют две таблицы для каждого имени столбца, существующего в обеих таблицах. Какой действительно здорово, когда у вас есть ключ 4 столбца, и вы устали от его ввода. Проблема возникает, когда Table1 имеет уже существующий столбец с именем DESCRIPTION, и вы добавляете новый столбец в Table2 с именем, О, я не знаю, что-то безобидное, например, МММ, описание, и теперь вы соединяете две таблицы в поле VARCHAR2(1000), которое является свободной формой.

предложение USING может привести к полной двусмысленности в дополнение к описанной выше проблеме. В другом так пост, кто-то показал это ANSI-92 SQL и попросил помочь прочитать его.

SELECT c.* 
FROM companies AS c 
JOIN users AS u USING(companyid) 
JOIN jobs AS j USING(userid) 
JOIN useraccounts AS us USING(userid) 
WHERE j.jobid = 123

Это совершенно неоднозначное. Я поместил столбец UserID как в компании, так и в пользовательские таблицы, и нет никаких жалоб. Что делать, если столбец UserID в компаниях является идентификатором последнего человека, который изменил эту строку?

Я серьезно, может кто-нибудь объяснить, почему такая двусмысленность была нужна? Почему он встроен прямо в стандарт?

Я думаю, что Билл прав, что есть большая база разработчиков, которые скопируйте / вставьте туда путь через кодирование. На самом деле, я могу признать, что я один, когда дело доходит до ANSI-92. Каждый пример, который я когда-либо видел, показывал, что несколько соединений вложены в круглые скобки. Честность, что делает выбор таблиц в sql трудно в лучшем случае. Но тогда sql92 evangilist объяснил, что на самом деле заставит порядок соединения. ИИСУС... все эти копипастеры, которые я видел, теперь фактически заставляют порядок соединения-работу, которая в 95% случаев лучше оставить оптимизаторам особенно копия/Пастер.

Томалак правильно понял, когда сказал:

люди не переключаются на новый синтаксис просто потому что она есть

Он должен дать мне что-то и я не вижу ног. А если есть и плюсы, то негативы-это Альбатрос слишком большой, чтобы его игнорировать.

на ум приходит несколько причин:

  • люди делают это по привычке
  • люди ленивы и предпочитают "старый стиль" присоединяется, потому что они вызывают меньше набирать
  • у новичков часто возникают проблемы, связанные с синтаксисом SQL-92 join
  • люди не переключаются на новый синтаксис только потому, что он есть
  • люди не знают о преимуществах нового (если вы хотите назвать это, что) синтаксис и, в первую очередь, что он позволяет вам для фильтрации таблицы до вы делаете внешнее соединение, а не после него, когда все, что у вас есть, - это предложение WHERE.

со своей стороны, я делаю все мои соединения в синтаксисе SQL-92, и я конвертирую код, где могу. Это более чистый, более читаемый и мощный способ сделать это. Но трудно убедить кого-то использовать новый стиль, когда они думают, что это вредит им с точки зрения большей работы по набору текста, не изменяя результат запроса.

в ответ на естественное соединение и использование сообщения выше.

Почему вы когда - нибудь видели необходимость использовать их-они не были доступны в ANSI-89 и были добавлены для ANSI-92 как то, что я могу видеть только как ярлык.

Я никогда не оставлю соединение на случай и всегда буду указывать таблицу/псевдоним и идентификатор.

для меня единственный путь-это ANSI-92. Он более подробен, и синтаксис не нравится последователям ANSI-89, но он аккуратно отделяет ваши соединения от ваших ФИЛЬТРУЮЩИЙ.

сначала позвольте мне сказать, что в SQL Server синтаксис внешнего соединения (*=) не дает правильных результатов все время. Бывают случаи, когда он интерпретирует это как перекрестное соединение, а не внешнее соединение. Так что есть веская причина, чтобы прекратить его использовать. И этот синтаксис внешнего соединения является устаревшей функцией и не будет в следующей версии SQL Server после SQL Server 2008. Вы все еще сможете сделать внутренние соединения, но почему на земле кто-то захочет? Они непонятны и гораздо сложнее поддерживать. Вы не можете знать, что является частью соединения и что это просто предложение where.

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

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

Я учился ANSI-89 в школе и работал в промышленности в течение нескольких лет. Тогда я покинул сказочный мир СУБД на 8 лет. Но потом я вернулся, и этот новый материал ANSI 92 преподавался. Я изучил синтаксис Join On, и теперь я действительно преподаю SQL, и я рекомендую новый синтаксис JOIN ON.

но недостаток, который я вижу, это коррелированные подзапросы, похоже, не имеет смысла в свете соединений ANSI 92. Когда информация о соединении была включена в WHERE и коррелирована подзапросы "соединяются" там, где все казалось правильным и последовательным. В ANSI 92 критерии соединения таблиц не находятся в WHERE и подзапросе "join", синтаксис кажется непоследовательным. С другой стороны, попытка "исправить" это несоответствие, вероятно, только ухудшит ситуацию.

Я не знаю ответа наверняка.. это вероисповедные войны (albiet в меньшей степени, чем Mac ПК или другим)

предположение заключается в том, что до недавнего времени, Оракул, (а может и других производителей также) не принял в соответствии со стандартом ANSI-92 стандарт (я думаю, что это было в Oracle версии 9 или около того) и так, для администраторов баз данных/БД разработчиков, работающих в компании, которые по-прежнему используют эти версии, (или хотел, чтобы код, чтобы быть портативный на серверах, которые могут использовать эти версии, они должны были придерживаться старый стандарт...

Это действительно позор, потому что новый синтаксис соединения гораздо более читаем, а старый синтаксис генерирует неправильные (неправильные) результаты в нескольких хорошо документированных сценариях.

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

инерция и практичность.

ANSI-92 SQL похож на сенсорный ввод. В некотором теоретическом смысле это может сделать все лучше когда-нибудь, но я могу печатать гораздо быстрее, глядя на клавиши с четырьмя пальцами сейчас. Мне нужно было бы идти назад, чтобы идти вперед, без гарантии, что когда-либо будет отдача.

написание SQL-это около 10% моей работы. Если мне нужен ANSI-92 SQL для решения проблемы, которую ANSI-89 SQL не может решить, я буду использовать его. (Я использую его в Access, in факт.) Если использование его все время поможет мне решить мои существующие проблемы гораздо быстрее, я бы потратил время, чтобы ассимилировать его. Но я могу вытащить ANSI-89 SQL, даже не задумываясь о синтаксисе. Мне платят за решение проблем-думать о синтаксисе SQL-это пустая трата моего времени и денег моего работодателя.

когда-нибудь, молодой Кузнечик, вы будете защищать свое использование синтаксиса ANSI-92 SQL от молодых людей, скулящих, что вы должны использовать SQL3 (или что-то еще). И тогда ты поймешь. : -)

у меня был запрос, который изначально был написан для SQL Server 6.5, который не поддерживал синтаксис SQL 92 join, т. е.

select foo.baz
from foo
  left outer join bar
  on foo.a = bar.a

вместо этого было написано как

select foo.baz
from foo, bar
where foo.a *= bar.a

запрос был вокруг в течение некоторого времени, и соответствующие данные накопились, чтобы сделать запрос выполняется слишком медленно, около 90 секунд для завершения. К моменту возникновения этой проблемы мы обновились до SQL Server 7.

после возни с индексами и другими пасхальными яйцами, я изменил соединение синтаксис должен быть совместим с SQL 92. Время выполнения запроса сократилось до 3 секунд.

есть веская причина для переключения.

репост от здесь.

Я могу ответить с точки зрения среднего разработчика, зная достаточно SQL, чтобы понять оба синтаксиса, но все же гуглить точный синтаксис вставки каждый раз, когда мне это нужно... :- P (Я не делаю SQL весь день, просто время от времени исправляя некоторые проблемы.)

ну, на самом деле, я нахожу первую форму более интуитивной, не делая видимой иерархии между двумя таблицами. Тот факт, что я изучил SQL с возможно старыми книгами, показывая первую форму, вероятно, не помогает... ; -)
И первая ссылка, которую я нахожу на sql select поиск в Google (который возвращает в основном французские ответы для меня...) сначала показывает старую форму (затем объясните вторую).

только давать некоторые подсказки на вопрос "почему"... ^_^ Я должен прочитать хорошую, современную книгу (DB agnostic) по этой теме. Если у кого-то есть предложения...

Я не могу говорить за все школы, но в моем университете, когда мы делали модуль SQL нашего курса, они не преподавали ANSI-92, они преподавали ANSI-89 - на старой системе VAX! Я не подвергался воздействию ANSI-92, пока не начал копаться в Access, построив некоторые запросы с помощью конструктора запросов, а затем копаясь в коде SQL. Понимая, что я понятия не имел, как он завершает соединения, или последствия синтаксиса, я начал копать глубже, чтобы понять оно.

конечно, есть те технические евангелисты, которые любят возиться и понимать, и это, как правило, те типы, которые принимают" новые " принципы и пытаются преобразовать остальное.

Как ни странно, мне кажется, что многие программисты выходят из школы и перестают продвигаться; думая, что это то, чему их учили, вот как это делается. Только когда вы снимаете свои шоры, вы понимаете, что школа была предназначена только для того, чтобы научить вас основам и дать вам достаточно понимания, чтобы узнать остальное самостоятельно, и что на самом деле вы едва поцарапали поверхность того, что нужно знать; Теперь ваша работа-продолжать этот путь.

Of конечно, это только мое мнение, основанное на моем опыте.

1) Стандартный способ записи внешнего соединения, по сравнению с *= или (+)=

2) ЕСТЕСТВЕННОЕ СОЕДИНЕНИЕ

3) в зависимости от компонента Database engine, ANSI-92 стремится быть более оптимальным.

4) ручной оптимизации :

предположим, что у нас есть следующий синтаксис (ANSI-89):

(1)select * from TABLE_OFFICES to,BIG_TABLE_USERS btu
where to.iduser=tbu.iduser and to.idoffice=1

это может быть написано как:

(2)select * from TABLE_OFFICES to
inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser
where to.idoffice=1

а также :

(3)select * from TABLE_OFFICES to
inner join BIG_TABLE_USERS btu on to.iduser=tbu.iduser and to.idoffice=1

все они (1),(2),(3) верните тот же результат, однако они оптимизированы по-разному, это зависит от СУБД, но большинство из них :

  • (1) его до ядра СУБД решить оптимизацию.
  • (2) он соединяет обе таблицы, а затем делает фильтр для каждого офиса.
  • (3) он фильтрует BIG_TABLE_USERS с помощью idoffice, а затем соединяет обе таблицы.

5) Более длинные запросы менее грязны.

Oracle не реализует ANSI-92 вообще хорошо. У меня было несколько проблем, не в последнюю очередь потому, что Таблицы данных в приложениях Oracle очень хорошо снабжены столбцами. Если количество столбцов в ваших соединениях превышает около 1050 столбцов (что очень легко сделать в приложениях), то вы получите эту ложную ошибку, которая не имеет абсолютно никакого логического смысла:

ORA-01445: cannot select ROWID from a join view without a key-preserved table.

переписывание запроса на использование синтаксиса соединения старого стиля заставляет проблему исчезнуть, что, похоже, указывает на вину непосредственно на реализацию стандарта ANSI-92 присоединяется.

пока я не столкнулся с этой проблемой, я был стойким сторонником ASNI-92, из-за преимуществ в снижении вероятности случайного перекрестного соединения, что слишком легко сделать с синтаксисом старого стиля.

причины, по которым люди используют ANSI-89 из моего практического опыта работы со старыми и молодыми программистами и стажерами и свежими выпускниками:

  • они изучают SQL из существующего кода, который они видят (а не книги), и изучают ANSI-89 из кода
  • ANSI-89 потому что меньше печатать
  • Они не думают об этом и используют тот или иной стиль и даже не знают, какой из них считается новым или старым, и им все равно
  • идея, что код также является связь со следующим программистом, идущим вместе с поддержанием кода, не существует. Они думают, что разговаривают с компьютером, а компьютеру все равно.
  • искусство "чистого кодирования" неизвестно
  • знание языка программирования и SQL особенно настолько плохо, что они копируют и вставляют вместе то, что они находят в другом месте
  • личные предпочтения

Я лично предпочитаю ANSI-92 и иногда меняю каждый запрос, который я вижу в синтаксисе ANSI-89 только чтобы лучше понять инструкцию SQL под рукой. Но я понял, что большинство людей, с которыми я работаю, недостаточно квалифицированы, чтобы писать объединения по многим таблицам. Они кодируют так хорошо, как могут, и используют то, что они запомнили в первый раз, когда они столкнулись с инструкцией SQL.

новый стандарт SQL наследует все от предыдущего стандарта, он же "кандалы совместимости". Таким образом, "старый" / "разделенный запятыми" / "неквалифицированный" стиль соединения является совершенно допустимым SQL-92 sytax.

Итак, я утверждаю, что SQL-92 это NATURAL JOIN Это единственное соединение вам нужно. Например, я утверждаю, что он превосходит inner join потому что он не генерирует повторяющиеся столбцы - нет больше переменных диапазона в SELECT предложения для устранения неоднозначности столбцов! Но я не могу ожидать, чтобы изменить каждое сердце и помните, поэтому мне нужно работать с кодерами, которые будут продолжать принимать то, что я лично считаю устаревшими стилями соединения (и они могут даже ссылаться на переменные диапазона как "псевдонимы"!). Такова природа командной работы, а не работы в вакууме.

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

вот несколько пунктов, сравнивающих SQL-89 и SQL-92 и проясняющих некоторые неправильные представления в других ответах.

  1. NATURAL JOINS - Это ужасная идея. Они неявны и требуют метаинформации о таблице. Ничто в SQL-92 не требует их использования так просто игнорировать их. Они не имеют отношения к этой дискуссии.
  2. USING - отличная идея, она имеет два эффекта:
    1. он производит только один столбец в результирующем наборе из равноденствия.
    2. это принуждает звук и здравый смысл конвенции. В SQL-89 у вас были люди, пишущие столбец id на обоих столах. После объединения таблиц это становится неоднозначным и требует явного сглаживания. Далее,ids на соединении почти наверняка были разные данные. Если вы присоединитесь к компании person, теперь вам нужно псевдоним one id до person_id и один id до company_id, без которого соединение будет производить два неясных колонны. С помощью глобально-уникальный идентификатор для суррогатного ключа таблицы-это соглашение стандартные награды с USING.
  3. синтаксис SQL-89 является неявным CROSS JOIN. А CROSS JOIN не уменьшает набор, он неявно его увеличивает. FROM T1,T2 это то же самое, что FROM T1 CROSS JOIN T2, что создает декартово соединение, которое обычно не то, что вы хотите. Имея избирательность, чтобы уменьшить, что удалено на Дальний WHERE условный означает, что вы с большей вероятностью совершите ошибки во время дизайн.
  4. SQL-89 , и SQL-92 явный JOINs имеют разный приоритет. JOIN имеет более высокий приоритет. Еще хуже, некоторые базы данных, такие как MySQL, очень долго ошибались.. Поэтому смешивание двух стилей-плохая идея, и гораздо более популярным стилем сегодня является стиль SQL-92.