10: SELECT INTOではコピーできないプロパティ
SQLのSELECT INTOは、次のような形で既存のテーブルからレコードをコピーして新しいテーブルを作成する。
SELECT list|* INTO newtable FROM sourcetable [WHERE condition]
しかし、このステートメントはテーブルを完全にコピーしてくれるわけではない。このステートメントは元のテーブルの主キー、インデックス、カラムとテーブルのプロパティは(デフォルトの設定以外は)コピーしてくれない。それに加え、Captionプロパティは無視され、元のカラムの名前が使われる。
SELECT INTOステートメントを使用する際には、スコープ内に新しいテーブルと同名のテーブル(newtableがすでに存在する場合、このステートメントは既存のテーブルを置き換えるということを念頭に置いておく必要がある。幸運なことに、SQLは最初に警告してくれる。一部のケースでは、エンジンは実際に新しいテーブルを作成する前に既存のテーブルを削除してしまう。この場合、何かまずいことがあっても元のテーブルがなくなってしまっているため、それに頼ることができない。もしnewtableがすでに存在するのであれば、SELECT INTOを実行する前にコピーを作っておいた方がいいだろう。また、この際にnewtableがオープンされている場合、SQLはエラーを返す。
新しいテーブルにデータをコピーする必要がないのであれば、次のようにWHERE句を追加して新たに空のテーブルを作ることもできる。
SELECT * INTO newtable FROM source WHERE FALSE
この場合、SQLはnewtableを作成するが、条件にはFALSEが指定されており、これを満たすことのできるレコードは存在しないため、データはコピーされない。
11: WHEREとHAVINGの違い
WHERE句とHAVING句は似た機能を持っているが、同じものではない。WHEREはSELECT句が返すデータを制限するものであるため、GROUP BYは重要ではない。エンジンはデータを比較し、グループ化を行う前にWHERE句の条件を満たさないレコードを切り捨てる。一方で、HAVING句はグループ化の条件を満たさないデータを切り捨てる。
どちらの句を使うかがよく分からないという人は、WHERE句はGROUP BY句の前に置かれているので、エンジンはレコードのグループ化を行う前にWHERE句を適用するという風に覚えておけばいいだろう。
12: UNIONの注意点
SQLのUNION操作は、次のような形で、異なるクエリやテーブルの結果得られるレコードを結合する。
SELECT1 list|* UNION SELECT2 list|*
UNIONについて覚えておくべき重要なことは、両方のSELECT句のカラム順が一致しなくてはならないということだ。カラム名が一致する必要はないが、どちらのリストにも同じ数のカラムがなくてはならず、データ型も適合していなくてはならない。データ型が一致しない場合、エンジンがもっとも合う型を選択する。その結果はうまくいくかも知れないが、うまくいかないかも知れない。
デフォルトではUNIONはレコードを最初のカラムの値によって並び替える。これは、UNIONが暗黙のうちにDISTINCT述語を使って、重複するレコードを省くためだ。重複しているものも含めて、すべてのレコードを含めるためには、UNION ALLを使用すればよい。これを使った場合、暗黙のうちに行われている並べ替えは実行されなくなる。重複レコードは存在しないことをあらかじめ知っており、レコードの数が非常に多い場合も、UNION ALLを使うことで性能を向上させることができる。これは、エンジンが(重複を見つけるために)必要な並べ替えの処理を飛ばすためだ。
この記事は海外CBS Interactive発の記事をシーネットネットワークスジャパン編集部が日本向けに編集したものです。 原文へ