あなたのユーザーはSQLについてまったく知らないかも知れないが、その価値についてはしっている可能性が高い。SQLはあらゆる場所で使われており、学ぶのも簡単で、SQLを使ったソリューションは実装も簡単だ。SQLをあまり使わないにしろ、よく使うにしろ、SQLを賢く使えば、エラーを避け、性能を向上させることができる。
多くのSQLは各ベンダー独自の仕様を持っている。以下で紹介するヒントはJetとTransact-SQLで使えるものだが、ほとんどのSQL製品はこれに似ている。
1: AccessのSQLウィンドウでJet SQLを利用する
Accessユーザーは、クエリを作成するたびにSQLステートメントを作成している。ただ、彼らがそれを知らないだけだ。彼らが使っているクエリデザインウィンドウは、実際にはSQLを視覚的に表現したものだ。ほとんどのユーザーは、自分が必要とする適切なSQLステートメントを作ることはできないため、視覚的なインターフェースは助けになるが、これはあなたも便利に使えるものだ。もし頭の中だけでエラーのないSQLコードを作ることができないのであれば、このSQLウィンドウに助けてもらうといいだろう。
- クエリデザインウィンドウを使ってクエリを作成し、そのSQLウィンドウのコードを、VBAモジュールのコード内にコピーする。
- もしそのコードのクエリが、VBAの無意味なエラーメッセージを返すようであれば、そのSQLステートメントをSQLウィンドウにコピーして実行してみるとよい。Accessは通常、エラーに関してVBAよりもましな情報を返してくれる。
モジュールの中のSQLステートメントを、そのままSQLウィンドウにコピーしてはいけない場合もある。ステートメントに連結演算子や変数が含まれている場合、定義ステートメントの直後にDebug.Printステートメントを追加しておくとよい。そして、ステートメントのデバッグが必要な場合は、評価後のステートメントをイミディエイトウィンドウからコピーする。たとえば、次のコード中のステートメントには変数と連結演算子が含まれているため、そのままではSQLウィンドウで実行することはできない。
"SELECT * FROM " & tbl & " ORDER BY " & fld
しかし、このステートメントの後にDebug.Printステートメントを付けておけば、イミディエイトウィンドウから、次のような評価後の結果をコピーすることができる。
SELECT * FROM Employees ORDER BY HireDate
2: SQLの予約語
SQLにはキーワードなどのいくつかの予約語がある。カラム、テーブル、変数、あらゆるオブジェクトの名前には、これらの単語は使えない。SQLエンジンが予想していないコンテクストでこれらのキーワードが使われると、SQLエンジンは混乱しエラーになる -- あるいはもっとひどい場合には、正しくない結果が出る。
3: ALL、DISTINCT、DISTINCTROWの違い
SQLのSELECTステートメントは、ALL、DISTINCT、DISTINCTROWという3つの述語をサポートしている。デフォルトはALLで、指定された条件を満たすすべてのレコードを返す。DISTINCTは、返してくるカラムに含まれる値を1つだけに制限する。たとえば、次のステートメントを実行すると、LastNameの値1つにつき、1つのレコードしか返されない。
SELECT DISTINCT LastName
言い方を変えれば、もしJohn SmithとMary Smithにそれぞれ1つのレコードが存在する場合、上記のステートメントはSmithという名字(LastName)に関してどちらか1つのレコードしか返さない。ただし、DISTINCTは直後に指定されたカラムだけでなく、それ以降に指定されたすべてのカラムに対して適用される。つまり、次のステートメントを使った場合、John SmithとMary Smithのどちらについても1つのレコードを返す。これは、その2つのカラムを組み合わせれば、同じレコードは生成されないためだ。
SELECT DISTINCT LastName, FirstName
SELECT句で1つ以上のカラムが指定されている場合、返されたレコードの選択されたカラムの値の組み合わせは一意となる。
DISTINCTには、ユーザーが知っておくべき、いくつかの予想しにくい特徴がある。
- DISTINCTをアスタリスクと一緒に使ってはならない。カラムは名前で指定する必要がある。
- これは当然のことだが、DISTINCTを使ったクエリの結果は更新することができない。
DISTINCTがカラムに対して使われるのに対し、DISTINCTROWはレコードに対して使われる。(Transact-SQLではDISTINCTROWはサポートされていない)。この述語には、以下に挙げるようないくつかの独自の制約があり、これがトラブルシュートが困難なエラーの原因になる場合もある。
- クエリにテーブルが1つしかない場合、エンジンはDISTINCTROWを無視する。
- 使用するすべてのテーブルのすべてのカラムが指定された場合、エンジンはDISTINCTROWを無視する。