バージョン 4.0
までは、ネストされたクエリのサポートは、INSERT
... SELECT ...
形式と REPLACE ... SELECT
...
形式だけに限定されています。
その他のコンテキストでは、IN()
構造を使用することができます。
サブクエリを含むクエリは、多くの場合、サブクエリなしのクエリに書き換えることができます。
SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);
上のクエリは次のように書き換えることができます。
SELECT t1.* FROM t1,t2 WHERE t1.id=t2.id;
次のクエリの場合、
SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2); SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);
次のように書き換えることができます。
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id WHERE table2.id IS NULL;
LEFT [OUTER] JOIN
は同等のサブクエリよりも迅速に実行されることがあります。なぜなら、LEFT
[OUTER] JOIN
のほうがサーバによる最適化がより適切に行われることがあるためです。これは、MySQL
Server
だけでなく、サーバ一般について言えます。
SQL-92
より前は外部結合が存在しなかったため、それまで、サブクエリは特定の処理を行う唯一の方法でした。しかし現在、MySQL
サーバを始めとする最新のデータベースシステムでは、さまざまな型の外部結合を提供しています。
より複雑なサブクエリでは、多くの場合、サブクエリを保持するためのテンポラリテーブルを作成することができます。しかし、一部のケースでは、この方法は有効ではありません。このようなケースの多くは、DELETE
ステートメントで発生します。この場合、標準
SQL
では、結合をサポートしていません(サブクエリ内を除く)。この状況には、次の
3
つの方法のいずれかで対処することができます。
第 1 の選択肢: MySQL バージョン 4.1 にアップグレードする。
第 2 の選択肢:
手続き型プログラミング言語(Perl や PHP
など)を使用し、SELECT
クエリを送信して削除対象のレコードの主キーを取得し、その後、それらの値を使用して
DELETE
ステートメント(DELETE FROM ... WHERE ...
IN (key1, key2, ...)
)を構築する。
第 3 の選択肢: 対話式 SQL で、MySQL の拡張
CONCAT()
を使用して(標準の
||
演算子の代わりに)、DELETE
ステートメントのセットを自動で構築する。
次はその例。
SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';') FROM tab1, tab2 WHERE tab1.col1 = tab2.col2;
このクエリをスクリプトファイルに保管することによって、ファイルからの入力を
mysql
コマンドラインインタープリタにリダイレクトし、さらにインタープリタの
2
つ目のインスタンスに出力を渡すことができる。
shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb
MySQL サーバ 4.0 では、複数テーブルの
DELETE
ステートメントをサポートしています。このようなステートメントを使用すると、1
つのテーブルのデータだけでなく、複数のテーブルのデータに基づくレコードを一度に効率的に削除することができます。
バージョン 4.0 以降では、複数テーブルの
UPDATE
ステートメントもサポートしています。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.