プロシージャを再帰する

階層構造(木構造)で深さが一定していないデータを辿ったりとか、
条件に合致するまで一定しない数をインクリメントしながら探索するロジックでは
再帰プログラムが有効。

PL/SQLでももちろんできる。
が、末尾最適化みたいなのは調べたけど全くヒットしないので、
再帰回数があまりに多い処理は考え物。

以下に、○週後の週末または月末を返すファンクションを記載
 CREATE OR REPLACE FUNCTION BPI_F_GET_WEEKEND(
 	p$DATE	IN DATE,
 	p$WEEK	IN NUMBER,
 	p$BEGIN_END	IN VARCHAR2
 )
 RETURN DATE
 /******************************************************************************/
 /* p$DATE      判定する月を入れる。日付も必要だが、月初日でなくてもよい       */
 /* p$WEEK      何週後かを数値で指定する                                       */
 /* p$BEGIN_END 週初め(日曜日)または週末(土曜日)を'B' or 'E'で指定する         */
 /* 使い方                                                                     */
 /* SELECT BPI_F_GET_WEEKEND('2010/01/01',1,'B')                               */
 /*       ,BPI_F_GET_WEEKEND('2010/01/01',1,'E')                               */
 /* FROM DUAL;                                                                 */
 /******************************************************************************/
 IS
 	p$START_DATE DATE;
 	p$RET_DATE DATE;
 BEGIN
 	-- 引数の日付を月初日に変換
 	p$START_DATE := TRUNC(p$DATE, 'MM');
 
 	-- 一週目の処理
 	IF p$WEEK = 1 THEN
 		IF p$BEGIN_END = 'B' THEN
 			RETURN p$START_DATE;
 		ELSIF p$BEGIN_END = 'E' THEN
 			-- 最初の週の土曜日取得
 			p$RET_DATE := NEXT_DAY(p$START_DATE - 1, '土');
 			RETURN p$RET_DATE;
 		END IF;
 	ELSE
 		-- 二週目以降は再帰した返り値にさらに加算
 		p$RET_DATE := BPI_F_GET_WEEKEND(p$START_DATE, p$WEEK - 1, 'E') + 1;
 
 		IF p$BEGIN_END = 'B' THEN
 			RETURN p$RET_DATE;
 		ELSIF p$BEGIN_END = 'E' THEN
 			p$START_DATE := TRUNC(p$RET_DATE, 'MM');
 			p$RET_DATE := NEXT_DAY(p$RET_DATE - 1, '土');
 			
 			RETURN LEAST(p$RET_DATE, LAST_DAY(p$START_DATE));
 		END IF;
 	END IF;
 
 EXCEPTION
 	WHEN OTHERS THEN
 		RETURN NULL;
 END;
 /

タグ:

+ タグ編集
  • タグ:
最終更新:2010年09月01日 14:04
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。