是select into 语句吗?捕获异常后处理。 (如果是update语句,可以在update语句之后用if SQL%NOTFOUND then) declare l_name varchar2(100); begin select ename into l_name from emp where empno = 10; dbms_output.put_line(l_name); exception when NO_DATA_FOUND then dbms_output.put_line('not found'); end;
试试这个: RecordCount number;select count(1) from table into RecordCount where ……;if RecordCount = 0 then …… end if;
cursor cur_cursor is select p.config_code, p.config_name from t_custom_table p;
cursor cur_Fcursor is select t.service_id, t.english_name, t.chinese_name from t_service_statistics t where t.garther_date >= trunc(sysdate) and t.flag = 0;
begin --如果当天有没有成功的数据 if cur_Fcursor%notfound then --这里就报错了 for fitem in cur_Fcursor loop pro_get_statistics(fitem.english_name, v_sql); --做更新操作 v_id := fitem.service_id; v_ename := fitem.english_name; v_cname := fitem.chinese_name; v_state := 1; -- v_flag end loop; else for titem in cur_cursor loop pro_get_statistics(titem.config_code, v_sql); --做更新操作 v_ename := titem.config_code; v_cname := titem.config_name; v_state := 2; end loop; end if; 不是这么个判断游标是否为空的吗?我看的资料全部都是这样诶,不知道为什么会报错,各位指点迷津啊~~~~~
刚刚测试了一下,你的这种写法是有问题的,如下:DECLARE CURSOR CUR_P IS SELECT P.CONFIG_CODE, P.CONFIG_NAME FROM T_CUSTOM_TABLE P; BEGIN OPEN CUR_P; --必须打开游标,否则会报 ORA-01001: 无效的游标 错误 --第一种,FOUND 后台打印出FOUND IF NVL(CUR_P%FOUND,TRUE) THEN DBMS_OUTPUT.PUT_LINE(''||'==>'||'FOUND'); END IF; --第二种,NOTFOUND 后台打印出FOUND IF NVL(CUR_P%NOTFOUND,TRUE) THEN DBMS_OUTPUT.PUT_LINE(''||'==>'||'NOTFOUND'); END IF; --第三种,输出了NOTFOUND IF CUR_P%NOTFOUND IS NULL THEN DBMS_OUTPUT.PUT_LINE(''||'==>'||'NOTFOUND'); END IF; --由此看来,打开游标之后,如果不用FETCH语句的话,返回的是空! 也就是NULL!! CLOSE CUR_P; END;
cursor cur_Fcursor is select t.service_id, t.english_name, t.chinese_name from t_service_statistics t where t.garther_date >= trunc(sysdate) and t.flag = 0;
begin open cur_Fcursor; --如果当天有没有成功的数据 if nvl(cur_Fcursor%found,true) then for fitem in cur_Fcursor loop pro_get_statistics(fitem.english_name, v_sql); --做更新操作 v_id := fitem.service_id; v_ename := fitem.english_name; v_cname := fitem.chinese_name; v_state := 1; -- v_flag end loop; else for titem in cur_cursor loop pro_get_statistics(titem.config_code, v_sql); --做更新操作 v_ename := titem.config_code; v_cname := titem.config_name; v_state := 2; end loop; end if;现在就是报 ORA-06511: PL/SQL: 游标已经打开 快崩溃了
我觉着: 你的NOTFOUND的判断用的不是很合适,你可以用SELECT COUNT(1) INTO N_NUM 游标定义中的查询,然后比较N_NUM >0 来做. 也许能更合适一点.
什么方式啊?难道在%found之后就关闭?可以给点意见吗?代码就更好了...
你的NOTFOUND的判断用的不是很合适
据说for循环里不需要显式的打开游标,你可以试一下,把锁定的账户解锁: create or replace procedure proc_user_locked authid current_user is v_username varchar2(255); cursor cur_user is select username from dba_users where account_status = 'EXPIRED & LOCKED'; begin for v_username in cur_user loop execute immediate 'alter user ' || v_username.username || ' account unlock'; dbms_output.put_line('alter user ' || v_username.username || ' account unlock'); end loop; commit; end;
...
end if
(如果是update语句,可以在update语句之后用if SQL%NOTFOUND then)
declare
l_name varchar2(100);
begin
select ename into l_name from emp where empno = 10;
dbms_output.put_line(l_name);
exception
when NO_DATA_FOUND then
dbms_output.put_line('not found');
end;
RecordCount number;select count(1) from table into RecordCount where ……;if RecordCount = 0 then
……
end if;
v_sql varchar2(1000);
v_obj varchar2(500);
v_num number;
v_date date;
--v_error varchar2(1000);
v_state number;
v_detail varchar(1000);
v_id number;
v_ename varchar2(500);
v_cname varchar2(1000);
v_flag number;
cursor cur_cursor is
select p.config_code, p.config_name from t_custom_table p;
cursor cur_Fcursor is
select t.service_id, t.english_name, t.chinese_name
from t_service_statistics t
where t.garther_date >= trunc(sysdate)
and t.flag = 0;
begin
--如果当天有没有成功的数据 if cur_Fcursor%notfound then --这里就报错了
for fitem in cur_Fcursor loop
pro_get_statistics(fitem.english_name, v_sql);
--做更新操作
v_id := fitem.service_id;
v_ename := fitem.english_name;
v_cname := fitem.chinese_name;
v_state := 1;
-- v_flag
end loop;
else
for titem in cur_cursor loop
pro_get_statistics(titem.config_code, v_sql);
--做更新操作
v_ename := titem.config_code;
v_cname := titem.config_name;
v_state := 2;
end loop;
end if;
不是这么个判断游标是否为空的吗?我看的资料全部都是这样诶,不知道为什么会报错,各位指点迷津啊~~~~~
这样查询出来的游标还要open吗,我之前的都没有啊,那可以直接用的吧...
CURSOR CUR_P IS
SELECT P.CONFIG_CODE, P.CONFIG_NAME FROM T_CUSTOM_TABLE P;
BEGIN
OPEN CUR_P; --必须打开游标,否则会报 ORA-01001: 无效的游标 错误
--第一种,FOUND 后台打印出FOUND
IF NVL(CUR_P%FOUND,TRUE) THEN
DBMS_OUTPUT.PUT_LINE(''||'==>'||'FOUND');
END IF;
--第二种,NOTFOUND 后台打印出FOUND
IF NVL(CUR_P%NOTFOUND,TRUE) THEN
DBMS_OUTPUT.PUT_LINE(''||'==>'||'NOTFOUND');
END IF;
--第三种,输出了NOTFOUND
IF CUR_P%NOTFOUND IS NULL THEN
DBMS_OUTPUT.PUT_LINE(''||'==>'||'NOTFOUND');
END IF;
--由此看来,打开游标之后,如果不用FETCH语句的话,返回的是空! 也就是NULL!!
CLOSE CUR_P;
END;
附几个变量的使用:
游标的属性 %found,%notfound,%isopen,%rowcount。
%found:若前面的fetch语句返回一行数据,则%found返回true,如果对未打开的游标使用则报ORA-1001异常。
%notfound,与%found行为相反。
%isopen,判断游标是否打开。
%rowcount:当前游标的指针位移量,到目前位置游标所检索的数据行的个数,若未打开就引用,返回ORA-1001。注:
no_data_found和%notfound的用法是有区别的,小结如下
1)SELECT . . . INTO 语句触发 no_data_found;
2)当一个显式光标(静态和动态)的 where 子句未找到时触发 %notfound;
3)当UPDATE或DELETE 语句的where 子句未找到时触发 sql%notfound;
4)在光标的提取(Fetch)循环中要用 %notfound 或%found 来确定循环的退出条件,不要用no_data_found。
select t.service_id, t.english_name, t.chinese_name
from t_service_statistics t
where t.garther_date >= trunc(sysdate)
and t.flag = 0;
begin
open cur_Fcursor;
--如果当天有没有成功的数据
if nvl(cur_Fcursor%found,true) then
for fitem in cur_Fcursor loop
pro_get_statistics(fitem.english_name, v_sql);
--做更新操作
v_id := fitem.service_id;
v_ename := fitem.english_name;
v_cname := fitem.chinese_name;
v_state := 1;
-- v_flag
end loop;
else
for titem in cur_cursor loop
pro_get_statistics(titem.config_code, v_sql);
--做更新操作
v_ename := titem.config_code;
v_cname := titem.config_name;
v_state := 2;
end loop;
end if;现在就是报 ORA-06511: PL/SQL: 游标已经打开 快崩溃了
但是,FOR循环不需要你打开游标.
这个还挺有意思的.需要换一种方式来做.
你的NOTFOUND的判断用的不是很合适,你可以用SELECT COUNT(1) INTO N_NUM 游标定义中的查询,然后比较N_NUM >0 来做.
也许能更合适一点.
create or replace procedure proc_user_locked
authid current_user is
v_username varchar2(255);
cursor cur_user is
select username
from dba_users
where account_status = 'EXPIRED & LOCKED';
begin
for v_username in cur_user loop
execute immediate 'alter user ' || v_username.username ||
' account unlock';
dbms_output.put_line('alter user ' || v_username.username ||
' account unlock');
end loop;
commit;
end;