while循环控制空数据集情况(Oracle PLSQL)
Controlling the empty dataset situation in while loop ( Oracle PLSQL )
我做了这个循环:
LOOP -- arranging loop
select num_aula, tipo_aula -- dataset A
into na, ta
from (
select num_aula,tipo_aula,abs(capienza-occ.score) -- dataset B
from aula
join(
select num_aula, tipo_aula -- dataset C
from aula
where tipo_aula = get_tipo_aula(occ.Nome_modulo,i)
minus
select num_aula, tipo_aula -- dataset D
from occr_lezione
where Nome_sede = occ.Nome_sede
and to_char(Data_fine_occr_lezione,'hh24mi') > to_char(occ.Data_inizio_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'hh24mi') < to_char(occ.Data_fine_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'dd-mm-yyyy') = to_char(occ.Data_inizio_occr_lezione,'dd-mm-yyyy'))
using(num_aula,tipo_aula)
order by y, num_aula
) where rownum=1;
i := i+1;
EXIT WHEN (na IS NOT NULL OR i > 2);
END LOOP; -- arranging loop end
i:=0;
其中数据集B是C和Dselect离子相差得到的table,数据集A是它的最小值。
现在数据集 B 可以为空,因此数据集 A 必须 select 编辑为空 table,这当然会导致空 selection。
因为这不是acceptable 在我的代码中,我做了一个循环,每次发生这种情况时都应该迭代。为了减少这种情况发生的次数,我将其中一个内部参数绑定到一个函数,它会根据 i 计数器给出不同的结果。
问题是每次数据集 B 结果为空时,编码此循环的过程都会停止给我这个错误:
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "ADMIN.ASS_AULE", line 45
ORA-06512: at line 1
我该如何解决这个问题?如何强制程序在循环结束之前不放弃?
所以,这是完整的功能,我尝试在底部添加异常处理程序,如您所见:
CREATE OR REPLACE PROCEDURE pprova
AS
CURSOR c1 is
select occr_lezione.*,
Cont_iscr_occr_lezione( Codice_corso,
Nome_modulo,
Data_inizio_ed_modulo,
Giorno_lezione,
Ora_inizio_lezione,
Data_inizio_occr_lezione
) score
from occr_lezione
where trunc(Data_inizio_occr_lezione) >= trunc(next_day(sysdate,'lunedi'))
and trunc(Data_inizio_occr_lezione) <= trunc(next_day(sysdate,'venerdi'))
and sem_check(sysdate,Data_inizio_ed_modulo) = 1
and year_check(Data_inizio_ed_modulo,sysdate) = 1
order by score ;
occ c1%ROWTYPE;
na NUMBER;
ta VARCHAR2(20);
sc NUMBER;
i NUMBER;
BEGIN
i := 0;
--
OPEN c1;
LOOP
FETCH c1 INTO occ;
EXIT WHEN c1%NOTFOUND;
IF occ.num_aula IS NULL AND occ.tipo_aula IS NULL
THEN
LOOP -- arranging loop
-- dataset A
select num_aula, tipo_aula
into na, ta
from (
-- dataset B
select num_aula,tipo_aula,abs(capienza-occ.score) y
from aula
join(
select num_aula, tipo_aula
from aula
where tipo_aula = get_tipo_aula(occ.Nome_modulo,i)
minus
select num_aula, tipo_aula
from occr_lezione
where Nome_sede = occ.Nome_sede
and to_char(Data_fine_occr_lezione,'hh24mi') > to_char(occ.Data_inizio_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'hh24mi') < to_char(occ.Data_fine_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'dd-mm-yyyy') = to_char(occ.Data_inizio_occr_lezione,'dd-mm-yyyy'))
using(num_aula,tipo_aula)
order by y, num_aula
) where rownum=1;
EXIT WHEN (na IS NOT NULL OR i > 2);
END LOOP; -- arranging loop end
i:=0;
UPDATE occr_lezione
SET Num_aula = na,
Tipo_aula = ta
WHERE Codice_corso = occ.Codice_corso
AND Nome_modulo = occ.Nome_modulo
AND Giorno_lezione = occ.Giorno_lezione
AND Ora_inizio_lezione = occ.Ora_inizio_lezione
AND Data_inizio_occr_lezione = occ.Data_inizio_occr_lezione;
END IF;
END LOOP; -- fine loop di fetching
EXCEPTION
WHEN no_data_found
THEN
IF i < 2
THEN NULL; -- Do nothing
ELSE RAISE_APPLICATION_ERROR (-20016,'non esistono combinazioni valide');
END IF;
END;
/
但是每次上面所说的数据集为空时,它都会跳过整个 select - 更新部分。
如果我在关注你的问题,听起来你想要捕获 no_data_found
异常
LOOP
BEGIN
<<your SELECT INTO>>
EXCEPTION
WHEN no_data_found
THEN
NULL; -- Do nothing
END;
i := i + 1;
...
END LOOP;
这假定您希望在 SELECT
语句 returns 没有数据时递增 i
。如果你想让你的一些逻辑只在SELECT
语句returns一行时执行,你可以把它放在BEGIN
和EXCEPTION
关键字之间。
不知道您要解决的问题,当我看到带有 rownum = 1
谓词的 SELECT INTO
时,我总是很担心。如果你的查询 returns 多行,你为什么要选择任意一行数据来填充你的局部变量?我很难想出很多有意义的案例。如果你想选择一个特定的行,明确地编码(即使用适当的 MAX
或 MIN
聚合函数,使用分析函数 rank
对行进行排名并选择一个,等等.)
因为我已经 post 编辑了完整的代码,所以我也会 post 解决方案 :
CREATE OR REPLACE PROCEDURE pprova
AS
CURSOR c1 is
select occr_lezione.*,
Cont_iscr_occr_lezione( Codice_corso,
Nome_modulo,
Data_inizio_ed_modulo,
Giorno_lezione,
Ora_inizio_lezione,
Data_inizio_occr_lezione
) score
from occr_lezione
where trunc(Data_inizio_occr_lezione) >= trunc(next_day(sysdate,'lunedi'))
and trunc(Data_inizio_occr_lezione) <= trunc(next_day(sysdate,'venerdi'))
and sem_check(sysdate,Data_inizio_ed_modulo) = 1
and year_check(Data_inizio_ed_modulo,sysdate) = 1
order by score ;
occ c1%ROWTYPE;
na NUMBER;
ta VARCHAR2(20);
sc NUMBER;
i NUMBER;
BEGIN
i := 0;
--
OPEN c1;
LOOP
FETCH c1 INTO occ;
EXIT WHEN c1%NOTFOUND;
IF occ.num_aula IS NULL AND occ.tipo_aula IS NULL
THEN
BEGIN
LOOP -- arranging loop
-- dataset A
select num_aula, tipo_aula
into na, ta
from (
-- dataset B
select num_aula,tipo_aula,abs(capienza-occ.score) y
from aula
join(
select num_aula, tipo_aula
from aula
where tipo_aula = get_tipo_aula(occ.Nome_modulo,i)
minus
select num_aula, tipo_aula
from occr_lezione
where Nome_sede = occ.Nome_sede
and to_char(Data_fine_occr_lezione,'hh24mi') > to_char(occ.Data_inizio_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'hh24mi') < to_char(occ.Data_fine_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'dd-mm-yyyy') = to_char(occ.Data_inizio_occr_lezione,'dd-mm-yyyy'))
using(num_aula,tipo_aula)
order by y, num_aula
) where rownum=1;
EXIT WHEN (na IS NOT NULL OR i > 2);
END LOOP; -- arranging loop end
EXCEPTION
WHEN no_data_found
THEN
IF i < 2
THEN NULL; -- Do nothing
ELSE RAISE_APPLICATION_ERROR (-20016,'non esistono combinazioni valide');
END IF;
i:=0;
END;
UPDATE occr_lezione
SET Num_aula = na,
Tipo_aula = ta
WHERE Codice_corso = occ.Codice_corso
AND Nome_modulo = occ.Nome_modulo
AND Giorno_lezione = occ.Giorno_lezione
AND Ora_inizio_lezione = occ.Ora_inizio_lezione
AND Data_inizio_occr_lezione = occ.Data_inizio_occr_lezione;
END IF;
END LOOP; -- fine loop di fetching
END;
/
正如 Justin 所指出的,异常范围由它所在的开始 - 结束代码块定义。这非常有趣,因为这意味着您实际上可以将代码分成块并为每个不同的异常处理程序定义.考虑到这一点,我只是将我的循环放在一个开始 - 结束块中并在其中声明处理程序。
我做了这个循环:
LOOP -- arranging loop
select num_aula, tipo_aula -- dataset A
into na, ta
from (
select num_aula,tipo_aula,abs(capienza-occ.score) -- dataset B
from aula
join(
select num_aula, tipo_aula -- dataset C
from aula
where tipo_aula = get_tipo_aula(occ.Nome_modulo,i)
minus
select num_aula, tipo_aula -- dataset D
from occr_lezione
where Nome_sede = occ.Nome_sede
and to_char(Data_fine_occr_lezione,'hh24mi') > to_char(occ.Data_inizio_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'hh24mi') < to_char(occ.Data_fine_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'dd-mm-yyyy') = to_char(occ.Data_inizio_occr_lezione,'dd-mm-yyyy'))
using(num_aula,tipo_aula)
order by y, num_aula
) where rownum=1;
i := i+1;
EXIT WHEN (na IS NOT NULL OR i > 2);
END LOOP; -- arranging loop end
i:=0;
其中数据集B是C和Dselect离子相差得到的table,数据集A是它的最小值。
现在数据集 B 可以为空,因此数据集 A 必须 select 编辑为空 table,这当然会导致空 selection。
因为这不是acceptable 在我的代码中,我做了一个循环,每次发生这种情况时都应该迭代。为了减少这种情况发生的次数,我将其中一个内部参数绑定到一个函数,它会根据 i 计数器给出不同的结果。
问题是每次数据集 B 结果为空时,编码此循环的过程都会停止给我这个错误:
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "ADMIN.ASS_AULE", line 45
ORA-06512: at line 1
我该如何解决这个问题?如何强制程序在循环结束之前不放弃?
所以,这是完整的功能,我尝试在底部添加异常处理程序,如您所见:
CREATE OR REPLACE PROCEDURE pprova
AS
CURSOR c1 is
select occr_lezione.*,
Cont_iscr_occr_lezione( Codice_corso,
Nome_modulo,
Data_inizio_ed_modulo,
Giorno_lezione,
Ora_inizio_lezione,
Data_inizio_occr_lezione
) score
from occr_lezione
where trunc(Data_inizio_occr_lezione) >= trunc(next_day(sysdate,'lunedi'))
and trunc(Data_inizio_occr_lezione) <= trunc(next_day(sysdate,'venerdi'))
and sem_check(sysdate,Data_inizio_ed_modulo) = 1
and year_check(Data_inizio_ed_modulo,sysdate) = 1
order by score ;
occ c1%ROWTYPE;
na NUMBER;
ta VARCHAR2(20);
sc NUMBER;
i NUMBER;
BEGIN
i := 0;
--
OPEN c1;
LOOP
FETCH c1 INTO occ;
EXIT WHEN c1%NOTFOUND;
IF occ.num_aula IS NULL AND occ.tipo_aula IS NULL
THEN
LOOP -- arranging loop
-- dataset A
select num_aula, tipo_aula
into na, ta
from (
-- dataset B
select num_aula,tipo_aula,abs(capienza-occ.score) y
from aula
join(
select num_aula, tipo_aula
from aula
where tipo_aula = get_tipo_aula(occ.Nome_modulo,i)
minus
select num_aula, tipo_aula
from occr_lezione
where Nome_sede = occ.Nome_sede
and to_char(Data_fine_occr_lezione,'hh24mi') > to_char(occ.Data_inizio_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'hh24mi') < to_char(occ.Data_fine_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'dd-mm-yyyy') = to_char(occ.Data_inizio_occr_lezione,'dd-mm-yyyy'))
using(num_aula,tipo_aula)
order by y, num_aula
) where rownum=1;
EXIT WHEN (na IS NOT NULL OR i > 2);
END LOOP; -- arranging loop end
i:=0;
UPDATE occr_lezione
SET Num_aula = na,
Tipo_aula = ta
WHERE Codice_corso = occ.Codice_corso
AND Nome_modulo = occ.Nome_modulo
AND Giorno_lezione = occ.Giorno_lezione
AND Ora_inizio_lezione = occ.Ora_inizio_lezione
AND Data_inizio_occr_lezione = occ.Data_inizio_occr_lezione;
END IF;
END LOOP; -- fine loop di fetching
EXCEPTION
WHEN no_data_found
THEN
IF i < 2
THEN NULL; -- Do nothing
ELSE RAISE_APPLICATION_ERROR (-20016,'non esistono combinazioni valide');
END IF;
END;
/
但是每次上面所说的数据集为空时,它都会跳过整个 select - 更新部分。
如果我在关注你的问题,听起来你想要捕获 no_data_found
异常
LOOP
BEGIN
<<your SELECT INTO>>
EXCEPTION
WHEN no_data_found
THEN
NULL; -- Do nothing
END;
i := i + 1;
...
END LOOP;
这假定您希望在 SELECT
语句 returns 没有数据时递增 i
。如果你想让你的一些逻辑只在SELECT
语句returns一行时执行,你可以把它放在BEGIN
和EXCEPTION
关键字之间。
不知道您要解决的问题,当我看到带有 rownum = 1
谓词的 SELECT INTO
时,我总是很担心。如果你的查询 returns 多行,你为什么要选择任意一行数据来填充你的局部变量?我很难想出很多有意义的案例。如果你想选择一个特定的行,明确地编码(即使用适当的 MAX
或 MIN
聚合函数,使用分析函数 rank
对行进行排名并选择一个,等等.)
因为我已经 post 编辑了完整的代码,所以我也会 post 解决方案 :
CREATE OR REPLACE PROCEDURE pprova
AS
CURSOR c1 is
select occr_lezione.*,
Cont_iscr_occr_lezione( Codice_corso,
Nome_modulo,
Data_inizio_ed_modulo,
Giorno_lezione,
Ora_inizio_lezione,
Data_inizio_occr_lezione
) score
from occr_lezione
where trunc(Data_inizio_occr_lezione) >= trunc(next_day(sysdate,'lunedi'))
and trunc(Data_inizio_occr_lezione) <= trunc(next_day(sysdate,'venerdi'))
and sem_check(sysdate,Data_inizio_ed_modulo) = 1
and year_check(Data_inizio_ed_modulo,sysdate) = 1
order by score ;
occ c1%ROWTYPE;
na NUMBER;
ta VARCHAR2(20);
sc NUMBER;
i NUMBER;
BEGIN
i := 0;
--
OPEN c1;
LOOP
FETCH c1 INTO occ;
EXIT WHEN c1%NOTFOUND;
IF occ.num_aula IS NULL AND occ.tipo_aula IS NULL
THEN
BEGIN
LOOP -- arranging loop
-- dataset A
select num_aula, tipo_aula
into na, ta
from (
-- dataset B
select num_aula,tipo_aula,abs(capienza-occ.score) y
from aula
join(
select num_aula, tipo_aula
from aula
where tipo_aula = get_tipo_aula(occ.Nome_modulo,i)
minus
select num_aula, tipo_aula
from occr_lezione
where Nome_sede = occ.Nome_sede
and to_char(Data_fine_occr_lezione,'hh24mi') > to_char(occ.Data_inizio_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'hh24mi') < to_char(occ.Data_fine_occr_lezione,'hh24mi')
and to_char(Data_inizio_occr_lezione,'dd-mm-yyyy') = to_char(occ.Data_inizio_occr_lezione,'dd-mm-yyyy'))
using(num_aula,tipo_aula)
order by y, num_aula
) where rownum=1;
EXIT WHEN (na IS NOT NULL OR i > 2);
END LOOP; -- arranging loop end
EXCEPTION
WHEN no_data_found
THEN
IF i < 2
THEN NULL; -- Do nothing
ELSE RAISE_APPLICATION_ERROR (-20016,'non esistono combinazioni valide');
END IF;
i:=0;
END;
UPDATE occr_lezione
SET Num_aula = na,
Tipo_aula = ta
WHERE Codice_corso = occ.Codice_corso
AND Nome_modulo = occ.Nome_modulo
AND Giorno_lezione = occ.Giorno_lezione
AND Ora_inizio_lezione = occ.Ora_inizio_lezione
AND Data_inizio_occr_lezione = occ.Data_inizio_occr_lezione;
END IF;
END LOOP; -- fine loop di fetching
END;
/
正如 Justin 所指出的,异常范围由它所在的开始 - 结束代码块定义。这非常有趣,因为这意味着您实际上可以将代码分成块并为每个不同的异常处理程序定义.考虑到这一点,我只是将我的循环放在一个开始 - 结束块中并在其中声明处理程序。