0

私のOracleデータベースで、動的テーブル名を使用するカーソルを使用して関数またはプロシージャを作成したいと思います。これが私のコードです。

CREATE OR REPLACE Function Findposition ( model_in IN varchar2,model_id IN number) RETURN number IS cnumber number;
TYPE c1 IS REF CURSOR;
c2 c1;
BEGIN
open c2 FOR 'SELECT id,ROW_NUMBER() OVER ( ORDER BY id) AS rownumber FROM '||model_in;
FOR employee_rec in c2
LOOP
    IF employee_rec.id=model_id then
    cnumber :=employee_rec.rownumber;
    end if;
END LOOP;
close c2;
RETURN cnumber;
END;

この問題を解決するのを手伝ってください。IN

4

2 に答える 2

2
  • c1弱い型の参照カーソルの型を宣言する必要はありません。タイプだけを使用できますSYS_REFCURSOR
  • このように、暗黙的なカーソル呼び出しと明示的なカーソル呼び出しを混在させることはできません。OPENカーソルに移動する場合はFETCH、ループ内でカーソルから移動する必要がありますCLOSE。できませんがOPENCLOSE暗黙のカーソルループでフェッチします。
  • データをフェッチする変数を宣言する必要があります。レコードタイプとそのレコードのインスタンスを宣言しましたが、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ことも、非常にわかりにくいため、問題があります。

于 2012-10-18T14:28:02.287 に答える
0

これを行うことができます。動的クエリを使用している場合はループは必要ありません

CREATE OR REPLACE Function Findposition(model_in IN varchar2,model_id IN number) 
RETURN number IS 
cnumber number;
TYPE c1 IS REF CURSOR;
c2 c1;
BEGIN
open c2 FOR 'SELECT rownumber 
             FROM (
            SELECT id,ROW_NUMBER() OVER ( ORDER BY id) AS rownumber 
            FROM '||model_in || ' 
                  ) WHERE id = ' || model_id;

FETCH c2 INTO cnumber;
close c2;

return cnumber;
END;
于 2012-10-18T14:35:14.523 に答える