web-dev-qa-db-ja.com

SQL ANSI-92標準がANSI-89よりもよく採用されないのはなぜですか?

私が働いたすべての会社で、人々はまだANSI-89標準でSQLクエリを書いていることがわかりました。

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-89を超えるANSI-92を使用することで、具体的なパフォーマンス上の利点はありますか?私は自分で試してみますが、ここにあるOracleのセットアップではEXPLAIN PLANを使用できません。コードを最適化しようとする人はいませんか?

104

テストした6つまたは8つのRDBMSブランドのPeter GulutzanとTrudy Pelzerによる「SQL Performance Tuning」によると、SQL-89スタイルの結合とSQL-92スタイルの結合の最適化またはパフォーマンスに違いはありませんでした。ほとんどのRDBMSエンジンは、クエリを最適化または実行する前に構文を内部表現に変換するため、人間が読み取れる構文には違いがありません。

また、SQL-92構文の伝道を試みます。承認されてから16年後、人々はそれを使い始めました!また、すべてのブランドのSQLデータベースでサポートされるようになったため、引き続き嫌悪感を使用する理由はありません(+) Oracle構文または*= Microsoft/Sybase構文。

SQL-89の習慣の開発者コミュニティを壊すことが非常に難しい理由については、書籍、雑誌の記事からの古代の例を使用して、コピー&ペーストでコーディングするプログラマーの大きな「ピラミッドのベース」があると想定できます。または別のコードベースであり、これらの人々は新しい構文を抽象的に学習しません。一部の人はパターンマッチし、一部の人は暗記法で学習します。

ただし、SQL-92構文を使用する人が以前よりも頻繁に使用されるようになっています。 1994年以来、オンラインでSQLの質問に答えています。

75
Bill Karwin

ANSI092標準には、かなり厄介な構文が含まれています。 自然結合 は1つで、USING句は別です。私見、テーブルへの列の追加はコードを壊すべきではありませんが、NATURAL JOINは最もひどい方法で壊れます。破壊する「最良の」方法は、コンパイルエラーです。たとえば、SELECT *のどこかで、列の追加couldがコンパイルに失敗します。失敗する次善の方法は、実行時エラーです。ユーザーに表示される可能性があるため、さらに悪いことですが、何かを壊したという素晴らしい警告が表示されます。 ANSI92を使用し、NATURAL結合でクエリを作成すると、コンパイル時に中断せず、実行時に中断せず、クエリが突然間違った結果を生成し始めます。これらのタイプのバグは潜行性です。レポートが間違っており、潜在的な財務情報の開示が間違っています。

NATURAL Joinsに不慣れな人向け。両方のテーブルに存在するすべての列名で2つのテーブルを結合します。 4列のキーがあり、入力するのにうんざりしているとき、これは本当にクールです。問題は、Table1にDESCRIPTIONという名前の既存の列があり、Table2に新しい列を追加するときに発生します。ああ、私は知りません。 (1000)自由形式のフィールド。

USING句は、上記の問題に加えて、完全なあいまいさを招く可能性があります。別の SO post で、誰かがこの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列がその行を最後に変更した人のIDである場合はどうなりますか?

私は真面目です、誰がそのようなあいまいさが必要なのか説明できますか?なぜ標準に直接組み込まれているのですか?

Billは、コーディングを通じてそこにコピー/貼り付けを行う開発者が大勢いることは正しいと思います。実際、ANSI-92に関して言えば、私は一種の人間だと認めることができます。私が見たすべての例は、括弧でネストされた複数の結合を示しました。正直なところ、SQLのテーブルを選択するのはせいぜい困難になります。しかし、その後、実際に結合順序を強制するSQL92エバンジリストが説明しました。イエス...私が見たすべてのコピー貼り付け者は、実際に結合順序を強制しています-95%の時間がオプティマイザーに残っている仕事特にコピー/ペースター。

トマラックは、彼が言ったとき、それを正しく理解しました、

そこにいるからといって、人々は新しい構文に切り替えません

それは私に何かを与えなければなりません、そして、私は逆さまを見ません。そして、もし良い面があるなら、ネガは無視できないほど大きなアホウドリです。

16
Mark Brady

いくつかの理由が思い浮かびます:

  • 人々は習慣からそれをします
  • 人々は怠け者であり、タイピングが少ないため「古いスタイル」の結合を好む
  • 初心者は、SQL-92結合構文に頭を悩ませる問題を抱えていることが多い
  • そこにいるからといって、人々は新しい構文に切り替えません
  • 人々は、新しい(あなたがそれを呼び出したいのであれば)構文が持つ利点を知らない、主にそれはあなたがテーブルをフィルタリングすることを可能にするということbefore haveはWHERE句です。

私の側では、SQL-92構文ですべての結合を行い、可能な限りコードを変換します。よりクリーンで読みやすく強力な方法です。しかし、クエリ結果を変更せずにタイピング作業が増えるという点で、新しいスタイルを使用するのが難しいと考える人を説得するのは困難です。

14
Tomalak

上記のNATURAL JOINおよびUSING投稿への応答。

なぜこれらを使用する必要があるのでしょうか?ANSI-89では使用できず、ショートカットとしてしか表示できないANSI-92に追加されました。

私は偶然に結合を離れることはなく、常にテーブル/エイリアスとIDを指定します。

私にとって、唯一の方法はANSI-92です。これはより冗長で、構文はANSI-89のフォロワーには好まれませんが、JOINSとFILTERINGをきちんと分離します。

10
Roger Bold

まず、SQL Serverでは、外部結合構文(* =)が常に正しい結果を与えるとは限りません。外部結合ではなく、クロス結合として解釈する場合があります。そのため、使用を中止する正当な理由があります。そして、その外部結合構文は非推奨の機能であり、SQL Server 2008以降のSQL Serverの次のバージョンには含まれません。内部結合を行うことはできますが、いったい誰がしたいのでしょうか。それらは不明確であり、維持するのがはるかに困難です。何が結合の一部であり、何が実際には単なるwhere句であるかを簡単に知ることはできません。

古い構文を使用するべきではないと考える理由の1つは、結合とそれらが何を実行し、何を実行しないかを理解することは、SQLコードを作成する人にとって重要なステップだからです。結合を完全に理解せずにSQLコードを記述しないでください。それらをよく理解していれば、おそらくANSI-92構文がより明確で保守しやすいという結論に達するでしょう。古い構文よりもANSI-92構文を優先して使用していないSQLの専門家に会ったことはありません。

古いコードを使用した人と出会った人や対処した人のほとんどは、結合を本当に理解していないため、データベースを照会するときに問題が発生します。これは私の個人的な経験であるため、常に真実だとは言いません。しかし、データスペシャリストとして、私は長年、このジャンクを信じられないほど修正しなければなりませんでした。

5
HLGEM

私は学校でANSI-89を教えられ、数年間業界で働きました。それから、DBMSの素晴らしい世界を8年間去りました。しかし、その後、私は戻ってきて、この新しいANSI 92の教材を教えていました。 Join On構文を学習しましたが、実際にSQLを教えています。新しいJOIN ON構文をお勧めします。

ただし、ANSI 92の結合を考慮すると、相関サブクエリは意味をなさないようです。結合情報がWHEREに含まれ、相関サブクエリがWHEREで「結合」されると、すべてが正しく一貫しているように見えました。 ANSI 92のテーブル結合条件はWHEREになく、サブクエリ「結合」は、構文に一貫性がないようです。一方、この不整合を「修正」しようとすると、おそらくさらに悪化します。

4
Scot McDermid

慣性と実用性。

ANSI-92 SQLはタッチタイピングに似ています。何らかの理論的な方法で、いつかすべてが良くなるかもしれませんが、4本の指でキーを見てもっと速く入力できます。私は前進するために後退する必要がありますが、それが見返りがあるという保証はありません。

SQLの作成は私の仕事の約10%です。 ANSI-89 SQLでは解決できない問題をANSI-92 SQLで解決する必要がある場合は、それを使用します。 (実際、Accessで使用しています。)常に使用することで既存の問題をより迅速に解決できる場合は、時間をかけてそれを吸収します。しかし、構文について考えることなくANSI-89 SQLを作成できます。私は問題を解決するために報酬を受け取ります。SQL構文について考えることは、私の時間と雇用主のお金の無駄です。

いつか、若いGrasshopper、あなたはSQL3(または何でも)を使うべきだと嘆く若者に対してANSI-92 SQL構文の使用を擁護するでしょう。そして、あなたは理解するでしょう。 :-)

2
JPLemme

もともとSQL Server 6.5用に作成されたクエリがありましたが、SQL 92の結合構文をサポートしていませんでした。

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秒に短縮されました。

切り替えるには正当な理由があります。

here から再投稿。

2
Dave

私は確かに答えを知りません..これは宗教戦争です(Mac-Pcや他のものよりも程度が低いとはいえ)

推測では、ごく最近まで、Oracle(および他のベンダーも)がANSI-92標準(Oracle v9またはその周辺にあったと思います)を採用していなかったため、DBA/Db開発者はまだこれらのバージョンを使用していました(または、これらのバージョンを使用している可能性のあるサーバー間でコードを移植できるようにするには、古い標準に準拠する必要がありました...

新しい結合構文がはるかに読みやすく、古い構文がいくつかのよく文書化されたシナリオで誤った(誤った)結果を生成するため、これは本当に残念です。

  • 具体的には、結合の「外部」側にある表の非結合関連列に条件付きフィルタリング述部がある場合の外部結合。
2
Charles Bretana

私はすべての学校について話すことはできませんが、私たちのコースでSQLモジュールを行っていた大学では、彼らはANSI-92を教えず、ANSI-89を教えました-古いVAXシステムで!クエリデザイナを使用していくつかのクエリを作成し、SQLコードを掘り下げてAccessを掘り下げ始めるまで、ANSI-92に触れることはありませんでした。結合がどのように完了するのか、または理解できるように深く掘り始めた構文の意味を理解していませんでした。

多くの場合、利用可能なドキュメントが正確に直観的でなく、人々は自分が知っていることに固執する傾向があり、多くの場合、仕事を遂行するために必要以上のことを学ぼうとしないことを考えると、採用にこれほど時間がかかっている理由を簡単に確認できます。

もちろん、いじくり回して理解するのが好きな技術的な伝道者がいます。そして、「新しい」原則を採用し、残りを変換しようとするタイプの傾向があります。

奇妙なことに、多くのプログラマーが学校を出て進学をやめているように思えます。これが彼らが教えられたものだからだ、と思ったのです。まばたきを外すまで、学校は基本を教えるだけで、残りを自分で学ぶのに十分な理解を与えることを目的としていること、そしてあなたが知っていることの表面をかろうじて傷つけただけだということに気付くのは初めてです。今、その道を続けるのはあなたの仕事です。

もちろん、それは私の経験に基づいた私の意見です。

1
BenAlabaster

SQL-89とSQL-92を比較し、他の回答の誤解を解消するいくつかのポイントを次に示します。

  1. NATURAL JOINSは恐ろしいアイデアです。暗黙的であり、テーブルに関するメタ情報が必要です。 SQL-92については何も使用する必要がないので、単純にそれらを無視します。これらはこの議論には関係ありません。
  2. USINGは素晴らしいアイデアであり、2つの効果があります。
    1. 等結合の結果セットには1つの列のみが生成されます。
    2. それは健全で健全な慣習を強制します。 SQL-89では、両方のテーブルに列idを書く人がいました。テーブルを結合すると、これはあいまいになり、明示的なエイリアスが必要になります。さらに、結合のidsにはほぼ確実に異なるデータがありました。人を会社に参加させる場合、1つのidperson_idにエイリアスし、1つのidcompany_idにエイリアスする必要があります。 。テーブルのサロゲートキーにグローバルに一意の識別子を使用することは、標準でUSINGが得られる規則です。
  3. SQL-89構文は、暗黙のCROSS JOINです。 CROSS JOINはセットを削減せず、暗黙的に成長させます。 FROM T1,T2FROM T1 CROSS JOIN T2と同じであり、通常は希望するものではないデカルト結合を生成します。削除されたものを選択することで、それを遠いWHERE条件に削除することは、設計中に間違いを犯しやすくなることを意味します。
  4. SQL-89 ,とSQL-92の明示的なJOINsの優先順位は異なります。 JOINの優先順位が高くなっています。さらに悪いことに、 MySQLのような一部のデータベースは非常に長い間これを誤っていました。 。したがって、2つのスタイルを混在させることは悪い考えであり、今日のはるかに人気のあるスタイルはSQL-92スタイルです。
1
Evan Carroll

老いも若きプログラマーと研修生と新卒者との私の実務経験から人々がANSI-89を使用する理由:

  • 彼らは(本ではなく)見ている既存のコードからSQLを学び、コードからANSI-89を学びます
  • ANSI-89は入力が少ないため
  • 彼らはそれについて考えず、1つまたは他のスタイルを使用し、両方のどちらが新しいか古いと考えられているかさえ知らず、どちらも気にしません
  • コードは、コードを保守している次のプログラマーとのコミュニケーションでもあるという考えは存在しません。彼らはコンピューターと話をしていると思いますが、コンピューターは気にしません。
  • 「クリーンコーディング」の技術は不明です
  • プログラミング言語とSQLの知識が特に乏しいため、他の場所で見つけたものをコピーして貼り付ける
  • 個人の好み

私は個人的にANSI-92を好み、ANSI-89構文に表示されるすべてのクエリを、手元のSQLステートメントをよりよく理解するために時々変更します。しかし、私が働いている人の大半は、多くのテーブルで結合を作成するのに十分なスキルを持っていないことに気付きました。彼らはできる限り良いコードを書き、最初にSQLステートメントに出会ったときに記憶したものを使用します。

1
hol

1)OUTER JOINを記述する標準的な方法、対* =または(+)=

2)ナチュラルジョイン

3)データベースエンジンに依存して、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)idofficeを使用してBIG_TABLE_USERSをフィルタリングし、両方のテーブルを結合します。

5)長いクエリは面倒ではありません。

1
magallanes

私は平均的な開発者の観点から答えることができ、両方の構文を理解するのに十分なSQLを知っていますが、必要なたびに挿入の正確な構文をグーグルで調べます... :-P(私は終日SQLをしません、時々いくつかの問題を修正するだけです。)

実際、最初のフォームはより直感的で、2つのテーブル間に明らかな階層はありません。おそらく古い本でSQLを学び、最初の形式を示したという事実は、おそらく役に立たないでしょう... ;-)
そして、私がsql select Googleで検索した最初の参照(ほとんどフランス語の答えを返す...)は、最初に古い形式を示しています(次に2番目の形式を説明します)。

「なぜ」という質問にいくつかのヒントを与えるだけです。誰か提案があれば...

1
PhiLho

新しいSQL標準は、以前の標準である「互換性の束縛」からすべてを継承します。したがって、「old」/「comma-separated」/「unqualified」結合スタイルは完全に有効なSQL-92構文です。

さて、必要なのはSQL-92のNATURAL JOINだけだと主張します。たとえば、重複する列を生成しないため、inner joinよりも優れていると主張します。列を特定するためのSELECT句に範囲変数はもうありません!しかし、すべての心と心を変えることは期待できないので、私が個人的にレガシー結合スタイルであると考えているものを採用し続けるコーダーと協力する必要があります(そして、それらは範囲変数を「エイリアス」と呼ぶことさえあります!)これはチームワークの性質であり、真空状態では動作しません。

SQL言語の批判の1つは、いくつかの意味的に等価な構文(リレーショナル代数を使用するもの、リレーショナル計算を使用するもの)を使用して同じ結果が得られることです。 。したがって、私はINNERと同じように、「古いスタイル」の結合に慣れています。それらをNATURALとして書き換えるのに時間がかかるかどうかは、コンテキストに依存します。

0
onedaywhen

OracleはANSI-92をまったく実装していません。特にOracle Appsのデータ表には列が非常に豊富にあるため、いくつかの問題がありました。結合内の列の数が約1050列を超える場合(Appsでは非常に簡単です)、この論理的な意味をなさない偽のエラーが発生します。

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

古いスタイルの結合構文を使用するようにクエリを書き直すと、問題が解消されます。これは、ANSI-92結合の実装に責任の指をまっすぐに向けているようです。

この問題に遭遇するまで、私はASNI-92の不動のプロモーターでした。これは、偶然のクロス結合の可能性を減らす利点があるためです。

しかし、今では、それを主張するのがはるかに難しいと感じています。彼らはオラクルの悪い実装を指摘し、「私たちは自分たちのやり方でやります、ありがとう」と言います。

0
Jonathan