はじめに
この Tips は初中級者向けです。
業務で SQL を書く人は多いと思いますが、その編集を行う際に使うエディタはこれといったデファクトスタンダードがなかったり別の言語の中で文字列として扱うことも少なからずあったりして、その記法などについて暗中模索をしている方が多いのではないでしょうか。
1分で理解できて、地味に効いてくる SQL の Tips を、__ひとつだけだと寂しいので__3つご紹介します。
動的に検索条件が決まる
プログラムの中で動的に SQL 文を組み立てる人は多いのではないでしょうか。「検索条件が指定されなければ全件検索」という SQL を組み立てる際に、下記のように WHERE
句をつけるかつけないかも動的にしていませんか?
// PHP のコード例です。
$sql = "
SELECT
*
FROM user_info
";
$and = " WHERE ";
// 検索条件に名前が指定された場合
if ($user_name != "") {
$sql .= $and. " user_name LIKE ". $user_name;
$and = " AND ";
}
// 検索条件に年齢が指定された場合
if ($age != "") {
$sql .= $and. " age = ". $age;
$and = " AND ";
}
検索条件を追加する処理が多く複雑になってくるといつ AND
が入ってくるのか分らなくなってきます。検索条件ごとに処理を入れなくてはなりません。また全件検索が指定される場合は WHERE
そのものが不要になる場合も。
そこで最初に「必ず真になる式」を書いておき、続く条件には必ず AND
を書くようにします。これだけでかなりコードが省略できます。
また、デバッグする際に条件を一つずつコメントアウトしたりするのにも便利です。
具体的には下記のようなコードになります。
$sql = "
SELECT
*
FROM user_info
WHERE 1=1 -- <-ここがポイントです
";
// 検索条件に名前が指定された場合
if ($user_name != "") {
$sql .= " AND user_name LIKE ". $user_name;
}
// 検索条件に年齢が指定された場合
if ($age != "") {
$sql .= " AND age = ". $age;
}
この Tips はどこかのサイトで見たものなのですが、どこだったのか失念してしまいました。
結合条件は必ず Join 句を使う
次のような SQL を書く人は多いでしょう。参考書などに書かれている最初のサンプルがそうですから。
SELECT
u.name,
a.zip_code
FROM user_info u,
address_info a
WHERE u.user_id = a.user_id
AND u.age < 20
私は、以下のように Inner Join を使って書いています。必ずそうしています。
SELECT
u.name,
a.zip_code
FROM user_info u
INNER JOIN address_info a
ON u.user_id = a.user_id
WHERE u.age < 20
「タイプ量が増えるだけで結果が同じ」と、あまりメリットが感じられないかもしれません。
しかしながら「結合のための条件を From 句の下に」「抽出のための条件を Where 句の下に」分離することができます。
結合するテーブルが増えてきてデバッグに苦労したり、忘れた頃にやってくる保守の時期になると、そのメリットが見えてくるのではないでしょうか。
テーブル名をキーワードと同じ行に書く
複数行に渡るような大きな SQL を書く場合、いろいろな記法があり現在までコレと言った決め手が無いのが悩みどころです。大きなシステムの保守を引き継いだ際に、テーブル名で grep した時に、どこでレコードを挿入したり削除したりしているかがわかるように INSERT INTO
、DELETE
、UPDATE
、FROM
らとテーブル名は同じ行に書いておいた方が良いと思いました。あまり美しくはないですが...。
INSERT INTO table_name
(...
DELETE table_name
WHERE...
UPDATE table_name
SET...
SELECT
*
FROM table_name...
ま、これもテーブル名が変数に入ってたりすると漏れは出てしまうのですが。
免責
コード例は説明のために極端に単純化しています。コード例以外の部分で基本的な事柄の説明が省略されているかもしれません。
【追記】
「説明のため極端に単純化」が通じない人が居たようなので追記します。最初に「初中級者」と書いたのに、確かにそれは不親切でもありました。
最初の Tips のように、文字列結合で SQL に値を渡してはいけません。プリペアドクエリを使ってください。例は説明用に極端な単純化をしているだけです。