Почему стандарт 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 ответов


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

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


ну стандарт ANSI092 включает в себя довольно отвратительный синтаксис. Естественные Соединения - Это одно и то используя П. Это другое. ИМХО, добавление столбца в таблицу не должно нарушать код, но естественное соединение ломается самым вопиющим образом. "Лучший" способ сломать-ошибка компиляции. Например, если вы выберете * somewhere, добавление столбца может ошибка компиляции. Следующий лучший способ потерпеть неудачу - Ошибка времени выполнения. Это хуже, потому что ваши пользователи может, и вижу, но все равно предупреждаю, что ты что-то сломал. Если вы используете 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 объяснил, что фактически заставит порядок соединения. ИИСУС... все эти копировальные пастеры, которые я видел, теперь фактически заставляют порядок соединения-задание, которое в 95% случаев лучше оставить оптимизаторам особенно копия/Пастер.

Tomalak получил это право, когда он сказал:

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

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


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

  • люди делают это по привычке
  • люди ленивы и предпочитают "старый стиль" присоединяется, потому что они вызывают меньше набирать
  • новички часто имеют свои проблемы, оборачивая голову вокруг синтаксиса 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 ПК или другим)

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

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

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

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

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

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

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


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

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

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


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

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

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


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

  1. NATURAL JOINS - Это ужасная идея. Они неявны и требуют метаинформации о таблице. Ничто в SQL-92 не требует их использования так просто игнорировать их. Они не имеют отношения к этому обсуждению.
  2. USING - отличная идея, она имеет два эффекта:
    1. он производит только один столбец в результирующем наборе из эквисоединения.
    2. это обеспечивает здоровую и здравую конвенцию. В SQL-89 у вас были люди, пишущие столбец id на обоих столах. После присоединения к таблицам это становится неоднозначным и требует явного сглаживания. Далее,ids на соединении почти наверняка имели разные данные. Если вы присоединитесь к человеку к компании, теперь вы должны псевдоним один id to person_id и один id to 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.