SQL

SQLは、関係データベース管理システム  において、データの操作や定義を行うためのデータベース言語、ドメイン固有言語である。プログラミングにおいてデータベースへのアクセスのために、他のプログラミング言語と併用される。

SQLが使われるRDBは「エドガー・F・コッドによって考案された関係データベースの関係モデルにおける演算体系である、関係代数と関係論理に基づいている」と宣伝されていることが多い。しかし、SQLについては、そのコッド自身をはじめ他からも、関係代数と関係論理にきちんと準拠していないとして批判されてはいる。

1. 標準SQL規格
----------

SQL規格は1986年に統一標準規格が発表されるまでは、その統一標準規格が存在しない状況であった。そのため、各関係データベース管理システム  ベンダーごとにさまざまな拡張がなされてきた。

近年になってANSI、後にISOで言語仕様の標準化が行われており、制定された年ごとにSQL86、SQL89、SQL92、SQL:1999、SQL:2003、SQL:2006、SQL:2008、SQL:2011などの規格があるが、対応の程度はベンダーごとにバラバラである。これは標準SQL策定に時間がかかりすぎたことにより、ビジネスの現状から早期の機能拡張が迫られたベンダーの都合と、独自構文を頻繁に利用していた利用者およびプログラマーに対し、互換性保持を保証する必要もあったためである。

そして1986年に統一標準規格が発表されて以来非常に多くの改正が行われた。制定年度順に代表的な規格を以下に挙げる。



2. SQLとオンライン処理
--------------

SQLはその性質上、「宣言型」の言語である。

2.1. SQLとプログラミング言語
------------------

プログラムから関係データベースを操作するための方法として、SQLが関係するものや関係しないものがあり、以下にそれらを述べる。

手続き型プログラミング言語、あるいは手続き型ではないプログラミング言語から関係データベースを操作するため、ソースコード中にSQLを埋め込み、プリプロセッサによってSQL部分を変換してデータベースアプリケーションを開発する方式がある。これを「埋め込みSQL」 と呼び、後にANSIにより仕様が標準化された。

マイクロソフトは、C言語からAPIレベルで統一したソースコードを記述し、クライアント・サーバ型アプリケーションシステムの構築に有用である仕組み「Open Database Connectivity」 を発表し、その有用性からANSIではODBC仕様を参考に「SQL/CLI」という仕様を標準化した。

LINQでは、プログラミング言語C#内において、文脈によって何らかの綴りをキーワードとして扱うという contextual keyword を活用し、言語内に言語の拡張のようにしてSQLライクな記述ができる。文字列ベースの埋め込みで発生するインジェクションに関係する問題や、プレースホルダの利用のようなわずらわしさが無いのが利点である。

3. SQLとバッチ処理
------------

埋め込みSQLやODBCの普及により、オンライントランザクション処理向きのSQLアクセス方法は確立されたが、バッチ処理性能向上の必要性が求められるようになった。

ある表 の内容を編集して別の表に格納する大量データの更新処理などをデータベースエンジン内部で処理プログラムを実行し、入出力  のほとんどをデータベース内部で完結することにより、クライアント側とのデータ通信によるオーバヘッドを削減することでバッチ処理性能を向上させる「ストアドプロシージャ」が考え出された。

ストアドプロシージャは、同じくデータベース内部に定義し、データベースに発生したイベントの内容に応じて任意の処理を実行する機能である「データベーストリガ」とともに、標準SQL仕様に採用され、SQL:1999  規格の永続格納モジュール  として標準化された。

しかし、標準化される以前から各関係データベース管理システム  ベンダーがデータベースエンジン内部で制御文法を記述し実行できるように独自の拡張が行われていたため、ストアドプロシージャの処理ロジック記述文法はそれ以前に標準化されたSQL文法と比較して著しい非互換が認められるため、アプリケーションソフトウェアの移植性・開発生産性・保守性を損なう場合がある。

標準SQLのSQL/PSMを採用したRDBMSを以下に挙げる。これらは概ね仕様に準拠しているが、仕様に定められていない部分や実装上の理由により細部には違いがある。

SQL/PSM 各RDBMSベンダーによる標準以外の独自のプロシージャには以下のようなものがある。これらには、独自追加された制御構文だけでなく、命令やデータ型の非互換も含むため注意が必要である。

PL/SQL 
Transact-SQL 
PL/pgSQL 
PSQL 

4. SQLの対話的実行
------------

SQLを対話的に実行する場合、関係データベース管理システム  に付属するコマンドラインタイプのアクセスユーティリティを利用するのが一般的である。SQL文を記述したテキストファイルをスクリプトとして実行し、バッチ的に実行することが可能なものもあり、広く利用されている。RDBMSごとに、そのユーティリティ固有の命令を備えているものもあるため、データベースを扱うアプリケーションソフトウェア開発の初心者はその命令もデータベースエンジンが解釈するSQL文法のひとつであると間違って覚えてしまい、ODBCやJDBCなどAPIからSQLを実行したときのエラーの原因が理解できずに混乱することもある。

ユーティリティ固有の文法で誤解しやすいものには、データベースでSQL文の文末に指定する文字である。全データベース共通では「;」、Oracle Database の ユーティリティであるSQL*Plusで、ストアドプロシージャの定義や無名PL/SQLブロックを発行するときに文末行に指定する「/」 や、Sybase/SQL Serverのisql/osqlではすべてのSQL文の文末行に指定する「GO」などがある。このなかでもっとも間違えやすいのが「;」である。これは、一般的なSQL教科書でも構文の終端文字として例が記載されているが、標準SQLの構文の終端文字ではない。

5. SQL文法
--------

5.1. コマンド種別
-----------

データベース言語SQLの文法の種別は、以下の3つに大別される。

データ定義言語 
データ操作言語 
データ制御言語 その他に、これらの命令の適用範囲を補完するための機能として、SQL文を実行時に解釈する「動的SQL」や、埋め込みSQLのための命令などが用意されている。関係データベース管理システム  以前のデータベース管理システム  では、これらは必ずしも同一の言語ではなかった。データ定義言語は存在せずにすべて専用のコマンドにパラメタを指定して実行する実装も存在した。

5.2. コマンド文法
-----------

5.2.1. データ定義言語
--------------

CREATE
DROP
ALTER

5.2.2. データ操作言語
--------------

INSERT INTO
UPDATE 〜 SET
DELETE FROM
SELECT 〜 FROM 〜 WHERE
後述する「動的SQL」でのSELECT文には、一度の実行で1行の結果を取得する「単一行SELECT文」と、カーソルにより複数行の結果を取得する「カーソルSELECT文」がある。列名と値を、対で指定 INSERT INTO 表名 VALUES

表を構成するすべての列に値を格納する場合は、列名の記述を省略可能 INSERT INTO 表名 VALUES 

他表のデータを検索して格納 INSERT INTO 表名1 SELECT 列名1, 列名2 FROM 表名2 〜

更新 UPDATE 表名 SET 列名2=値2, 列名3=値3 WHERE 列名1=値1

削除 DELETE FROM 表名 WHERE 列名1=値1

1行以上の検索 SELECT * FROM 表名 WHERE 列名1 BETWEEN 値1 AND 値2 ORDER BY 列名1

1行だけの検索 SELECT * INTO 受け取り変数 FROM 表名 WHERE 列名1=値1

取得行数を指定した検索 SELECT * FROM 表名 LIMIT 取得行数

5.2.3. データ制御言語
--------------

GRANT
REVOKE
SET TRANSACTION
BEGIN
COMMIT
ROLLBACK
SAVEPOINT
LOCK

5.2.4. カーソル定義・操作
----------------

「カーソル」とは、SELECT文などによるデータベース検索による検索実行の結果を1行ずつ取得して処理するために、データベースサーバ側にある結果集合と行取得位置を示す概念をいう。 カーソルの定義とその操作は、主にアプリケーションプログラムなどの手続き型言語からのSQL実行において利用する。

DECLARE CURSOR
OPEN
FETCH
UPDATE
DELETE
CLOSE

5.2.4.1. カーソル宣言例
----------------

DECLARE CR1 CURSOR FOR SELECT CLMA, CLMB, CLMC FROM TBL1 WHERE CLMA BETWEEN :V開始値 AND :V終了値 ※V開始値、V終了値は、埋め込み変数あるいはホスト変数と呼ばれ、埋め込みSQLの場合は、プログラム中のBEGIN DECLARE SECTION〜END DECLARE SECTIONの間で宣言する。

5.2.4.2. カーソルのオープン例
-------------------

OPEN CR1 ※カーソルのオープン前に、V開始値、V終了値には値を設定しておく。

5.2.4.3. 行の取り出し例
----------------

FETCH CR1 INTO :V列A, :V列B, :V列C 検索条件に合致した行をすべて取り出すには、「データなし」になるまでFETCHを繰り返す。

※V列A, :V列B, :V列C は、埋め込み変数あるいはホスト変数と呼ばれ、埋め込みSQLの場合は、プログラム中のBEGIN DECLARE SECTION〜END DECLARE SECTIONの間で宣言する。

取り出した行の更新例 UPDATE TBL1 SET CLMB=CLMB+1, CLMC=:V列C更新値 WHERE CURRENT OF CR1 FETCHで位置付けた行を更新するには、UPDATE文でWHERE CURRENT OF カーソル名を指定する。

※V列C更新値は、埋め込み変数あるいはホスト変数と呼ばれ、埋め込みSQLの場合は、プログラム中のBEGIN DECLARE SECTION〜END DECLARE SECTIONの間で宣言する。

取り出した行の削除例 DELETE FROM TBL1 WHERE CURRENT OF CR1 FETCHで位置付けた行を削除するには、DELETE文でWHERE CURRENT OF カーソル名を指定する。

カーソルのクローズ例 CLOSE CR1

5.2.5. 動的SQL
------------

動的SQLは、通常SQL文をRDBMSに対して送信の度にデータベースエンジンで実行可能な内部中間コードに翻訳する作業を事前に行うことによって、翻訳済みSQLコードを再度利用してSQL解析のオーバーヘッドを削減することと、SQL文をソースコードで固定せずにデータベースへのアクセス毎に構文を書き換えたい場合に、有用である。データ操作言語  ももちろん実行できるが、データ定義言語  のようにデータベース製品の機能アップによって新しい命令が追加されるものは、プリプロセッサの対応作業が重荷になるため、ほとんどのデータベース製品ではDDL文は動的SQLにて実行することが一般的となっている。

PREPARE
EXECUTE

5.2.6. 埋め込みSQL
--------------

もともとカーソルは、埋め込みSQLでホスト言語から結果集合を取得するために、都合のよい方法として考えられたものである。データベースと通信するためのリソースの割り当て確保や解放、1行ごとにホスト言語のループ処理で取得するための命令  などがある。

ALLOCATE  DESCRIPTOR　
WHENEVER
SQLSTATE EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 77 XPARM PIC X. 01 XTBL1. 03 XCLMA PIC X. 03 XCLMB PIC X. 01 XTBL2. 03 XCLM1 PIC S9 COMP-3. 03 XCLM2 PIC S9 COMP. EXEC SQL END DECLARE SECTION END-EXEC.

EXEC SQL DECLARE CR1 CURSOR FOR SELECT CLMA, CLMB FROM TBL1 WHERE CLMA>=:XPARM ORDER BY CLMA END-EXEC.

EXEC SQL WHENEVER SQLERROR GO TO ERR--PROC END-EXEC.

SQLの静的実行MOVE 'ABC' TO XPARM. EXEC SQL OPEN CR1 END-EXEC. PERFORM TEST BEFORE UNTIL SQLCODE NOT = ZERO EXEC SQL FETCH CR1 INTO :XCLMA, :XCLMB END-EXEC IF SQLCODE = ZERO データ検索時の処理 END-IF END-PERFORM. IF SQLCODE = 100 EXEC SQL CLOSE CR1 END-EXEC END-EXEC.

SQLの動的実行EXEC SQL PREPARE PRESQL FROM 'INSERT INTO TBL2  VALUES' END-EXEC. MOVE ZERO TO XCLM2. PERFORM TEST AFTER VARYING XCLM1 FROM 1 BY 1 UNTIL XCLM1 >= 10 EXEC SQL EXECUTE PRESQL USING :XCLM1, :XCLM2 END-EXEC END-PERFORM. GOBACK. ERR--PROC. 例外処理<WtXmlEndTag />

5.2.7. 3値論理
-----------

　SQLで用いられる論理値は、コンピュータの世界でもっとも広く利用されている2値論理  ではなく、3値論理  となっている。 3値論理自体は古くから存在し、Fortran など数値計算においてはよく用いられる。

5.2.8. 再帰
---------

　Oracle 9i 以来 CONNECT BY 構文がサポートされるようになり、ネットワーク型のデータ構造の処理が軽くなった。すなわち、再帰的な処理を行うさいに、ホスト側が再帰的な処理を負担するとデータサーバーとのトラフィックが増大し、その間はコミットされるまで他のサーバがデータサーバーにアクセスできないという問題があった。それを解消するために「データサーバー内で再帰的な処理を行う」というアプローチが試みられた。とはいえ、「SQL で再帰を書く」というプログラマは珍しがられた。

6. 主な SQL
---------

MySQL
PostgreSQL
Ingres
SQLite
Firebird
Oracle Database
Microsoft SQL Server
IBM DB2 (プロプライエタリ、AS/400、z/OS、UNIX、Linux、Windows対応）