RDBMSごとのWITH句の実装の差異
WITH句は一時表を作成する句で,SQL99より規格に取り入れられた.しかしながら,各RDBMSのWITH句の実装はまちまちである.
次のSQL文を見てみよう.
WITH foo(a, b) AS ( SELECT 1, 2 UNION SELECT 3, 4 ) SELECT * FROM foo
このSQL文を実行すると,PostgreSQLとSQL Serverでは次のような結果を得る.(表示形式はRDBMSによって若干異なる.)
a | b ----+---- 1 | 2 3 | 4
さらに,PostgreSQLはWITH句の中でSELECT文のほかにVALUES句を用いることもできるので,次のSQL文でもPostgreSQLの場合に限り受理され,先に示した例と同様の結果を得る.これにより,PostgreSQLでは既存の表を参照しないWITH句をほかのRDBMSの場合に比較して簡潔に書くことが可能である.
WITH foo(a, b) AS ( VALUES (1, 2), (3, 4) ) SELECT * FROM foo
OracleでもWITH句をサポートしているが,この例のように既存の表をひとつも参照しないSELECT文をサポートしていないのでこのSQL文は受理されない*1.しかしながら,既存の表を参照する場合は受理される.表tblが存在し,次のSQL文による問い合わせに対しそれに続く結果が返るとする.
SELECT * FROM tbl
n ---- 3 4 5 6 7
次のSQL文はOracleでも受理され,それに続く結果を返す.
WITH bar(n) AS ( SELECT * FROM tbl WHERE MOD(n, 2) = 0 ) SELECT * FROM bar
n ---- 4 6
一方,MySQLではWITH句による一時表の作成をサポートしていない.遺憾である.
*1:このような場合は,FROM句にdual表を指定することが一般的に行われる.