sql >> データベース >  >> RDS >> Oracle

動的テーブル名を使用したOracle関数とカーソル

    • 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 という名前のカーソルを宣言する 非常に説明的でないため、問題もあります。



    1. SQL*Plusスクリプトを終了させる

    2. MySQL安全な更新モードを使用していて、WHEREなしでテーブルを更新しようとしました

    3. IN式のJPQLLOWER関数

    4. Android- SqliteHelper.onCreate()にテーブルが存在するかどうかを確認する必要がありますか?