はじめに
PL/SQLには「ストアドファンクション」という関数がありますが、ある時に「ストアドファンクションが関数ということは、もしかするとストアドファンクションを使って再帰処理をすることができるのでは?」と思い立ち、フィボナッチ数をテーマにして再帰処理が作れるかを調べてみました。
使用した環境
- Oracle社が提供しているOracle Live SQLでOracle19cを利用しました。
フィボナッチ数の概要
- フィボナッチ数はよく知られた数列の一つで、「最初の2つの項は0と1で、それ以降の項は直前の2つの項の和となる」というものです。
フィボナッチ数の概要
F(0) = 0
F(1) = 1
F(2) = F(1) + F(0) = 1 + 0 = 1
F(3) = F(2) + F(1) = 1 + 1 = 2
F(4) = F(3) + F(2) = 2 + 1 = 3
...
- これを数式で表すと、以下のようになります。
F(0) = 0
F(1) = 1
F(n+2) = F(n+1) + F(n)
作成したストアドファンクション
- 以下のように、フィボナッチ数の定義をそのままストアドファンクションとして書きました。
- 第0項目から第n項目までのフィボナッチ数を1つずつ求めるため、実行用のSQL側ではFOR文を使っています。
- 以下の
実行結果
では、「55」が第10項目(n=10)のフィボナッチ数となります。 - なお、今回はOracle Live SQLを利用させてもらっているため、負荷を極力小さくするため、ストアドファンクションの引数に指定する値は小さい方が望ましいと思います。
calc_fibonacci.sql
-- フィボナッチ数を返すストアドファンクション
CREATE OR REPLACE FUNCTION calc_fibonacci(n IN NUMBER) RETURN NUMBER
-- 宣言部
IS
-- 処理部
BEGIN
IF (n=0) THEN
RETURN 0;
ELSIF (n=1) THEN
RETURN 1;
ELSE
RETURN calc_fibonacci(n-2) + calc_fibonacci(n-1);
END IF;
END;
実行用SQL
-- 宣言部
DECLARE
n NUMBER;
fib_result NUMBER;
BEGIN
n := 10;
DBMS_OUTPUT.PUT_LINE('Calculate Fibonacci number: F(0)~F(' || n || ')');
DBMS_OUTPUT.PUT_LINE('----------');
FOR i IN 0..n LOOP
fib_result := calc_fibonacci(i);
DBMS_OUTPUT.PUT_LINE('F(' || i || ')' || '=' || fib_result);
END LOOP;
END;
実行結果
Calculate Fibonacci number: F(0)~F(10)
----------
F(0)=0
F(1)=1
F(2)=1
F(3)=2
F(4)=3
F(5)=5
F(6)=8
F(7)=13
F(8)=21
F(9)=34
F(10)=55
まとめ
- コンパイルエラーも起きず、意外にもサクッと再帰処理を実装&実行することができました。
- 再帰処理そのものはマシンに負担をかける処理なので、再帰させる回数をある程度小さくした方が良いと思います。
- 負荷の高い処理になるので、業務では避けた方が良いと思います。