在我的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;
帮我解决这个问题。
答案 0 :(得分:2)
c1
类型。您只需使用SYS_REFCURSOR
类型。OPEN
光标,则必须在循环中FETCH
,并且必须CLOSE
它。您不能OPEN
和CLOSE
,但可以在隐式游标循环中从中获取它。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;