来年はじめのリリースを目指して開発中のPostgreSQL 8.4の姿が見え始めてきた。今回は8.4の新機能の目玉の一つである「再帰SQLのサポート」を中心にお話しする。

 開発にあたっては,PostgreSQLの大規模利用ユーザーである住友電工情報株式会社がリソースを提供し,筆者の勤務するSRA OSS日本支社がPostgreSQLコミュニティとの調整および実装を担当した。最終的にはPostgreSQLコアメンバらの協力で実装がブラッシュアップされ,8.4への取り込みが確定した。

プログラミング言語における再帰処理

 再帰処理はCやJavaなどの通常のプログラミングでは普通にサポートされており,うまく使うと効率のよいプログラムをきれいに書くことができる。再帰処理は再帰的な構造を持つデータ,例えば木構造やリスト構造を処理する際に良く使われる。

データベースにおける再帰処理

 再帰SQLとは,文字通りSQL文を使ってこのような再帰処理を行うことを指す。SQLはもともと集合演算に基づく関係代数をサポートするために開発された言語であり,手続き的な概念である再帰とはなじみが薄く,オブジェクト指向的機能などと同様,SQL標準の世界でサポートされたのはわりと最近のことで,2003年にリリースされたSQL:2003からになる。SQL標準の再帰SQLをサポートしている製品は,商用データベースではDB2,SQL Serverなど,オープンソースデータベースでは筆者が知る限り Firebirdがある(Oracleは独自構文で再帰SQLを実装している)。

WITH句とは

 SQL標準の構文で再帰処理を行うには,「WITH句」というものを使う。なじみが薄い読者もいるかもしれないので,簡単に説明しよう。WITH句は以下のように書く。

WITH [RECURSIVE] AS (共通テーブル式) 問合わせ本体;

 問合わせ本体は普通のSELECT文で,「共通テーブル式」には,名前を付けた問合わせの定義を書く。この名前は「共通テーブル式名」と呼ばれ,「問合わせ本体」の中でテーブル式として引用できる。複雑なSELECT文を一度定義しておいて再利用するという意味では,ビューに良く似ている。ビューとの違いはその定義が該当SQL文の中だけで有効だという点だ。わざわざビューを作るまでもない時に便利だと言えよう。

 ここで「RECURSIVE」というキーワードを使えば再帰的な定義を記述できるが,まずは再帰を含まない場合を見ていこう。

再帰を含まないWITH句

 非常に単純なWITH句の例を示す。

WITH w1 AS (SELECT * FROM t1) SELECT * FROM w1;

 (SELECT * FROM t1)が共通テーブル式で,それに付けた名前がw1である。そして,問合わせ本体がSELECT * FROM w1になる。結局,上のSQLは

SELECT * FROM t1;

 を回りくどい方法で実行しているに過ぎないが,WITH句の書式はご理解頂けたと思う。