データベース●●○○○

SQL

リレーショナルデータベースへの問い合わせ言語。宣言的にデータを取り出す。

概要

SQL(Structured Query Language)は、RDBMSに対してデータの問い合わせや更新を行うための言語です。最大の特徴は「どうやって取るか」の手順ではなく「何が欲しいか」という条件を書く宣言的なスタイルにあります。SELECT name FROM users WHERE age >= 20 と書けば、データベースが最適な取り出し方を自分で考えて結果を返してくれます。

PostgreSQL、MySQL、SQLiteなど製品は違っても、基本文法はISO/IECで標準化されたほぼ共通のSQLです。一度身につければデータベースをまたいで通用する、ソフトウェア開発で最も息の長いスキルの一つと言えます。バックエンド開発だけでなく、データ分析やBI(可視化)ツールの世界でも共通言語として使われています。

なぜ生まれたか

リレーショナルモデルが提唱される以前のデータベースでは、データを取り出す手順——どのレコードからポインタをたどり、どの順で読むか——をプログラマが逐一書く必要がありました。データの物理的な配置を知らなければ問い合わせが書けず、配置が変わればプログラムも壊れる。データを使いたいだけの人にとって、あまりに敷居が高い世界でした。

1970年代、IBMのサンノゼ研究所でリレーショナルモデルを実装する実験システム System R が開発され、その問い合わせ言語として SEQUEL(後のSQL)が設計されました。目標は「手続きを知らなくても、欲しい結果を英語に近い形で宣言できること」です。取り出し方の最適化はデータベース側(オプティマイザ)の仕事になり、人間は「何が欲しいか」に集中できるようになりました。この分業こそがSQLの発明の本質で、1986年にANSI標準となって以降、リレーショナルデータベースの事実上の共通語であり続けています。

詳細

問い合わせの基本形

SQLの中心はSELECT文です。FROM で対象のテーブルを指定し、WHERE で行を絞り込み、SELECT で欲しい列を選びます。さらに ORDER BY で並べ替え、GROUP BY と集計関数(COUNT、SUMなど)でグループごとの集計ができます。そしてRDBMSの真価を引き出すのが JOIN で、外部キーでつながった複数のテーブルを結合し、「顧客名と注文内容を並べて表示する」といった問い合わせを1文で表現できます。

FROM(対象の表を決める)JOIN(関連する表を結合)WHERE(行を絞り込む)GROUP BY(集計単位にまとめる)SELECT(列を選ぶ)ORDER BY(並べ替える)
SELECT文の論理的な評価順序。書く順序と評価順序が違う点がつまずきどころ

注意したいのは、SQLを書く順序(SELECTが先頭)と論理的な評価順序(FROMが先)が一致しないことです。「WHEREではSELECTで付けた別名が使えない」といった初学者の混乱の多くは、この評価順序を知ると解消します。

4つの役割

SQLは役割ごとにいくつかの部分言語に分かれています。データを読み書きするDML(SELECT / INSERT / UPDATE / DELETE)、テーブルなどの構造を定義するDDL(CREATE / ALTER / DROP)、権限を制御するDCL(GRANT / REVOKE)、そしてトランザクションを制御するTCL(BEGIN / COMMIT / ROLLBACK)です。日常の開発で最も触れるのはDMLですが、マイグレーション(スキーマ変更)ではDDLを、整合性が重要な処理ではTCLを使います。

SQLDML ─ データ操作SELECT / INSERTUPDATE / DELETEDDL ─ 構造定義CREATE / ALTERDROPDCL ─ 権限制御GRANT / REVOKETCL ─ Tx制御BEGIN / COMMITROLLBACK
SQLを構成する4つの部分言語。日常の開発で最も触れるのはDML

実行計画とパフォーマンス

宣言的な言語であるがゆえに、同じ結果を返すSQLでも実行のされ方は大きく変わります。データベースはSQLを受け取ると、統計情報をもとに「どのインデックスを使うか」「テーブルをどの順で結合するか」を決めた実行計画を立てます。EXPLAIN 文でこの計画を確認でき、「インデックスが使われずテーブル全体を走査していた」といった遅さの原因を突き止められます。SQLが書けることと、速いSQLが書けることの間には、この実行計画を読む力の差があります。

実務での落とし穴

実務上、最も重大な落とし穴がセキュリティです。ユーザーの入力を文字列連結でSQLに埋め込むと、入力に紛れ込ませた命令が実行されるSQLインジェクションの脆弱性になります。必ずプレースホルダ(パラメータ化クエリ)を使い、値と命令を分離するのが鉄則です。

また、アプリケーションからはORMを通じてSQLを間接的に発行することが多くなりましたが、ORMが生成するSQLの良し悪しを判断するにも、結局は素のSQLと実行計画を読む力が必要です。方言(LIMIT句の書き方や日付関数など製品ごとの差異)はあるものの、標準SQLの基礎はどの現場でも通用します。「まず標準的な書き方を身につけ、必要になったら方言を調べる」という学び方が効率的です。