--个人网站同步更新 www.dbaleading.com
前些天,有个朋友问我关于动态SQL做游标的题,他有一个存储过程,使用了动态SQL做游标,可是怎么调试都没有结果出来,请我帮忙看看.等他把文件发给我一看,呵呵,他这个动态SQL是类似这么用的:
DECLARE
V_ID NUMBER ;
v_1 NUMBER ;
CURSOR CUR_1 IS
SELECT ID FROM TEST WHERE ID = V_ID ;
BEGIN
V_ID := 3 ;
OPEN cur_1 ;
LOOP
FETCH cur_1
INTO v_1 ;
EXIT WHEN cur_1%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_1);
END LOOP;
CLOSE cur_1;
END;
看起来没什么问题,可是在他的机器上就是调试不出结果,我把V_ID给他换成常量后,马上就有返回值,同时,我在我自己的库上做DEMO测试,也是可以通过的,这就奇怪了,他的数据库也是9206的,而且也不报错,就是没有output,邪门了,呵呵,再试,给他换一种写法,变成下面这样:
DECLARE
v_1 NUMBER ;
v_2 NUMBER ;
CURSOR cur_2(v_id NUMBER ) IS
SELECT ID FROM test2 WHERE ID=v_id;
BEGIN
v_1 := 1 ;
OPEN cur_2(v_1) ;
LOOP
FETCH cur_2
INTO v_2 ;
EXIT WHEN cur_2%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_2);
END LOOP;
CLOSE cur_2;
END;
这样总没问题了吧,我可是找了9i和10g几套库测试过都通过的呵,给他再测试,还是没结果,这下子郁闷了,这时候已经是夜里12点了,跟他卯上了,再换写法,就不信这个邪了,上面的两种写法都是基于PL/SQL语法的,下面我用DBMS_SQL这个ORACLE提供的包来做,虽然麻烦点,只要有用,咱就试试吧,改成下面这样:
declare
v_curId integer;
v_sql varchar2(1000);
v_well_id varchar2(100);
v_ret number(3);
v_id varchar2(10);
begin
v_id := 'abcdefgh';
v_sql := 'SELECT ID FROM TEST3 WHERE ID = LOWER('||chr(39)||v_id||chr(39)||')';
v_curId := DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(v_curId, v_Sql, DBMS_SQL.V7);
DBMS_SQL.DEFINE_COLUMN(v_curId, 1, v_well_id, 128);
v_ret := DBMS_SQL.EXECUTE(v_curId);
loop
if DBMS_SQL.FETCH_ROWS(v_curId) = 0 then
exit;
end if;
DBMS_SQL.COLUMN_VALUE(v_curId, 1, v_well_id);
DBMS_OUTPUT.PUT_LINE(v_well_id);
end loop;
DBMS_SQL.CLOSE_CURSOR(v_curid);
end;
哈哈,这次oracle老实了,在他那边可以返回结果集了,OK,就这样,让朋友按照这个方法去改存储过程了,夜也深了,没精力再折腾了,就这么了结了, 估计是因为他那边有些选件没装吧,后来因为我自己没环境,没再做更深的研究,上面几种,就当是使用动态SQL做游标的总结吧,呵呵.
查看全部回复
我也来说两句
