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它然后在一个隐式游标循环中从中获取。
  • 您必须声明一个变量(或多个变量)才能将数据提取到其中。我声明了一个记录类型和该记录的一个实例,但您可以轻松地声明两个局部变量并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 回答