oracle函数和游标使用动态表名

时间:2012-10-18 14:08:21

标签: oracle11g

在我的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;

帮我解决这个问题。

2 个答案:

答案 0 :(得分:2)

  • 无需为弱类型的引用游标声明c1类型。您只需使用SYS_REFCURSOR类型。
  • 你不能像这样混合隐式和显式游标调用。如果您要OPEN光标,则必须在循环中FETCH,并且必须CLOSE它。您不能OPENCLOSE,但可以在隐式游标循环中从中获取它。
  • 您必须声明一个变量(或变量)来获取数据。我声明了记录类型和该记录的实例,但您可以轻松地将两个局部变量和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 :(得分: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;