c1
を宣言する必要はありません 弱く型付けされた ref カーソルの型。SYS_REFCURSOR
を使用するだけです 入力してください。- このように暗黙的カーソル呼び出しと明示的カーソル呼び出しを混在させることはできません。
OPEN
する場合 カーソル、FETCH
する必要があります ループでそれからCLOSE
する必要があります それ。OPEN
ことはできません そしてCLOSE
暗黙のカーソル ループでそこからフェッチします。 - データを取得する変数を宣言する必要があります。レコード タイプとそのレコードのインスタンスを宣言しましたが、2 つのローカル変数と
FETCH
を簡単に宣言できます。 それらの変数に変換します。 ROWID
は予約語なのでROWPOS
を使用しました
それをまとめると、次のように書くことができます
SQL> ed
Wrote file afiedt.buf
1 CREATE OR REPLACE Function Findposition (
2 model_in IN varchar2,
3 model_id IN number)
4 RETURN number
5 IS
6 cnumber number;
7 c2 sys_refcursor;
8 type result_rec is record (
9 id number,
10 rowpos number
11 );
12 l_result_rec result_rec;
13 BEGIN
14 open c2 FOR 'SELECT id,ROW_NUMBER() OVER ( ORDER BY id) AS rowpos FROM '||model_in;
15 loop
16 fetch c2 into l_result_rec;
17 exit when c2%notfound;
18 IF l_result_rec.id=model_id
19 then
20 cnumber :=l_result_rec.rowpos;
21 end if;
22 END LOOP;
23 close c2;
24 RETURN cnumber;
25* END;
SQL> /
Function created.
これにより、期待どおりの結果が返されると思います
SQL> create table foo( id number );
Table created.
SQL> insert into foo
2 select level * 2
3 from dual
4 connect by level <= 10;
10 rows created.
SQL> select findposition( 'FOO', 8 )
2 from dual;
FINDPOSITION('FOO',8)
---------------------
4
効率の観点からは、カーソルを開いて毎回テーブルからすべての行をフェッチするよりも、これを単一の SQL ステートメントとして記述した方がはるかに優れていることに注意してください。カーソルを使用することに決めた場合は、テーブルからすべての行をフェッチし続けるのではなく、目的の行が見つかったときにカーソルを終了することをお勧めします。
コードの明快さの観点からすると、変数名とデータ型の多くは奇妙に見えます。パラメータ名が適切に選択されていないようです- model_in
は期待できません たとえば、入力テーブルの名前になります。 c2
という名前のカーソルを宣言する 非常に説明的でないため、問題もあります。