PL/SQL: ORA-01001 在游标使用中
PL/SQL: ORA-01001 in cursor use
我正在编写一个 PL/SQL 函数来检查日期和 return 一个日期。
问题是测试隔离的功能我得到了关于光标使用的错误。
ORA-01001: cursor no válido or in english, not valid cursor.
我使用两个数组来保存不同类型的日期。
但是错误出现在 FOR ... LOOP
循环中。先验是明确定义游标和行变量。
我已经检查过并且行变量包含行,查询 returns 至少有 5 行。
这里是函数的代码:
create or replace FUNCTION OBTAIN_DATE_FIN_ABSENT
(combination IN VARCHAR2 DEFAULT '',
otarif1 IN VARCHAR2 DEFAULT '',
otarif2 IN VARCHAR2 DEFAULT '',
indicador IN NUMBER DEFAULT 0)
RETURN DATE
AS
i NUMBER := 1;
solution DATE := '01/01/1970';
previousOTARi VARCHAR2(3 CHAR) := '';
TYPE varray_type IS VARRAY(50) OF DATE; -- Création deux arrays des dates.
v1 varray_type; -- array date_begin
v2 varray_type; -- array date_end
-- Requete pour obtenir tous les lignes pour la combinaison passé.
cursor cursorDate is
select cin.cin_value cin_combi, cin.date_begin date_begin, cin.date_end date_end, gin.code gcode, gin.otari_file otari_file
from rs2qtcin cin, rs2qtgin gin
where cin.group_id = gin.id
and cin.cin_value = combination
and substr(gin.otari_file, 1, 1) = substr(otarif1, 1, 1)
order by cin.date_begin, gin.otari_file;
my_cursorDate cursorDate%rowtype;
BEGIN
--open cursorDate;
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro!');
FETCH cursorDate INTO my_cursorDate;
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro1!');
IF cursorDate%FOUND THEN -- El cursor contiene info, sino %NOTFOUND
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro2!');
IF cursorDate%ROWCOUNT != 0 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor NO vacío!');
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor VACÍO!!!');
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Cursor NOTFOUND!');
END IF;
FOR my_cursorDate IN cursorDate LOOP
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro3!');
--v1(i) := my_cursorDate.date_begin;
--v2(i) := my_cursorDate.date_end;
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Guardadas ambas fechas en array!.');
IF v2(i-1) = NULL THEN
--solution := v1(i); -- Guardamos date_begin de la siguiente iteración
IF indicador = 1 and previousOTARi = otarif1 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- OK!');
ELSE
IF indicador = 2 and previousOTARi = otarif2 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- ¡CHECK! this case.');
END IF;
END IF;
END IF;
--solution := 1;
previousOTARi := my_cursorDate.otari_file;
i := i+1;
END LOOP;
--close cursorDate;
RETURN solution;
EXCEPTION WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
Open 和 close cursor 语句被注释了,因为我正在调试代码。但是当它们被取消注释时,错误是一样的。
打开光标后,您需要将其关闭。
此外,我已将您的光标更改为使用现代显式连接。
这部分我也修改了你的代码FOR rec IN cursorDate LOOP
create or replace FUNCTION OBTAIN_DATE_FIN_ABSENT
(combination IN VARCHAR2 DEFAULT '',
otarif1 IN VARCHAR2 DEFAULT '',
otarif2 IN VARCHAR2 DEFAULT '',
indicador IN NUMBER DEFAULT 0)
RETURN DATE
AS
i NUMBER := 1;
solution DATE := '01/01/1970';
previousOTARi VARCHAR2(50) := '';
TYPE varray_type IS VARRAY(50) OF DATE;
v1 varray_type;
v2 varray_type;
cursor cursorDate is
select cin.cin_value cin_combi
, cin.date_begin date_begin
, cin.date_end date_end
, gin.code gcode
, gin.otari_file otari_file
from rs2qtcin cin
join rs2qtgin gin on cin.group_id = gin.id
and cin.cin_value = gin.combination
and substr(gin.otari_file, 1, 1) = substr(cin.otarif1, 1, 1)
order by cin.date_begin, gin.otari_file;
my_cursorDate cursorDate%rowtype;
BEGIN
open cursorDate;
FETCH cursorDate INTO my_cursorDate;
IF cursorDate%FOUND THEN -- El cursor contiene info, sino %NOTFOUND
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro2!');
IF cursorDate%ROWCOUNT != 0 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor NO vacío!');
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor VACÍO!!!');
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Cursor NOTFOUND!');
END IF;
close cursorDate;
FOR rec IN cursorDate LOOP
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro3!');
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Guardadas ambas fechas en array!.');
IF v2(i-1) = NULL THEN
IF indicador = 1 and previousOTARi = otarif1 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- OK!');
ELSE
IF indicador = 2 and previousOTARi = otarif2 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- ¡CHECK! this case.');
END IF;
END IF;
END IF;
previousOTARi := my_cursorDate.otari_file;
i := i+1;
END LOOP;
RETURN solution;
EXCEPTION WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
/
您的程序存在一些结构性问题。最紧迫的问题是 "open and close cursor statement are commented because i'm debugging the code"。因为 open 在注释中 FETCH 失败并带有无效游标 - fetch 需要打开游标。您声称错误是在游标 FOR 循环上发出的。我想那是在您评论开放之前。游标 FOR 为游标发出一个打开。其中,如果游标打开,则抛出无效游标。您不能在打开的游标上使用游标 FOR。因此,您要么打开游标,处理第一行(获取),然后关闭游标,然后输入 FOR。退出循环后不要关闭游标。
您在嵌套 if 结构中存在逻辑问题。
IF cursorDate%FOUND THEN -- El cursor contiene info, sino %NOTFOUND
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro2!');
IF cursorDate%ROWCOUNT != 0 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor NO vacío!');
ELSE
"if cursorDate%Rowcount != 0" 将始终 return 为真。游标属性 %rowcount returns 从游标中获取的行数。如果最后一次提取 return 一行,属性 %Found returns 为真。因为这里 %Rowcount 是从属的 %Found 意味着它永远不会 return 小于 1。
另一个显而易见的语句是
IF v2(i-1) = NULL THEN
它有两个问题。首先,你的变量 i 被初始化为 1,所以上面的语句然后读取 v2(0)。这是无效的,pl/sql 中的索引值以 1 开头。一旦正确,结果语句将永远不会为真。您不能将关系运算符与 Null 一起使用;这样做的结果始终为 Null。你需要 "v2(i) is Null"。
如果您仍然有问题,请解决这些问题 post 另一个问题。
我正在编写一个 PL/SQL 函数来检查日期和 return 一个日期。 问题是测试隔离的功能我得到了关于光标使用的错误。 ORA-01001: cursor no válido or in english, not valid cursor.
我使用两个数组来保存不同类型的日期。
但是错误出现在 FOR ... LOOP
循环中。先验是明确定义游标和行变量。
我已经检查过并且行变量包含行,查询 returns 至少有 5 行。
这里是函数的代码:
create or replace FUNCTION OBTAIN_DATE_FIN_ABSENT
(combination IN VARCHAR2 DEFAULT '',
otarif1 IN VARCHAR2 DEFAULT '',
otarif2 IN VARCHAR2 DEFAULT '',
indicador IN NUMBER DEFAULT 0)
RETURN DATE
AS
i NUMBER := 1;
solution DATE := '01/01/1970';
previousOTARi VARCHAR2(3 CHAR) := '';
TYPE varray_type IS VARRAY(50) OF DATE; -- Création deux arrays des dates.
v1 varray_type; -- array date_begin
v2 varray_type; -- array date_end
-- Requete pour obtenir tous les lignes pour la combinaison passé.
cursor cursorDate is
select cin.cin_value cin_combi, cin.date_begin date_begin, cin.date_end date_end, gin.code gcode, gin.otari_file otari_file
from rs2qtcin cin, rs2qtgin gin
where cin.group_id = gin.id
and cin.cin_value = combination
and substr(gin.otari_file, 1, 1) = substr(otarif1, 1, 1)
order by cin.date_begin, gin.otari_file;
my_cursorDate cursorDate%rowtype;
BEGIN
--open cursorDate;
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro!');
FETCH cursorDate INTO my_cursorDate;
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro1!');
IF cursorDate%FOUND THEN -- El cursor contiene info, sino %NOTFOUND
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro2!');
IF cursorDate%ROWCOUNT != 0 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor NO vacío!');
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor VACÍO!!!');
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Cursor NOTFOUND!');
END IF;
FOR my_cursorDate IN cursorDate LOOP
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro3!');
--v1(i) := my_cursorDate.date_begin;
--v2(i) := my_cursorDate.date_end;
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Guardadas ambas fechas en array!.');
IF v2(i-1) = NULL THEN
--solution := v1(i); -- Guardamos date_begin de la siguiente iteración
IF indicador = 1 and previousOTARi = otarif1 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- OK!');
ELSE
IF indicador = 2 and previousOTARi = otarif2 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- ¡CHECK! this case.');
END IF;
END IF;
END IF;
--solution := 1;
previousOTARi := my_cursorDate.otari_file;
i := i+1;
END LOOP;
--close cursorDate;
RETURN solution;
EXCEPTION WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
Open 和 close cursor 语句被注释了,因为我正在调试代码。但是当它们被取消注释时,错误是一样的。
打开光标后,您需要将其关闭。
此外,我已将您的光标更改为使用现代显式连接。
这部分我也修改了你的代码FOR rec IN cursorDate LOOP
create or replace FUNCTION OBTAIN_DATE_FIN_ABSENT
(combination IN VARCHAR2 DEFAULT '',
otarif1 IN VARCHAR2 DEFAULT '',
otarif2 IN VARCHAR2 DEFAULT '',
indicador IN NUMBER DEFAULT 0)
RETURN DATE
AS
i NUMBER := 1;
solution DATE := '01/01/1970';
previousOTARi VARCHAR2(50) := '';
TYPE varray_type IS VARRAY(50) OF DATE;
v1 varray_type;
v2 varray_type;
cursor cursorDate is
select cin.cin_value cin_combi
, cin.date_begin date_begin
, cin.date_end date_end
, gin.code gcode
, gin.otari_file otari_file
from rs2qtcin cin
join rs2qtgin gin on cin.group_id = gin.id
and cin.cin_value = gin.combination
and substr(gin.otari_file, 1, 1) = substr(cin.otarif1, 1, 1)
order by cin.date_begin, gin.otari_file;
my_cursorDate cursorDate%rowtype;
BEGIN
open cursorDate;
FETCH cursorDate INTO my_cursorDate;
IF cursorDate%FOUND THEN -- El cursor contiene info, sino %NOTFOUND
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro2!');
IF cursorDate%ROWCOUNT != 0 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor NO vacío!');
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor VACÍO!!!');
END IF;
ELSE
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Cursor NOTFOUND!');
END IF;
close cursorDate;
FOR rec IN cursorDate LOOP
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro3!');
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Guardadas ambas fechas en array!.');
IF v2(i-1) = NULL THEN
IF indicador = 1 and previousOTARi = otarif1 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- OK!');
ELSE
IF indicador = 2 and previousOTARi = otarif2 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- ¡CHECK! this case.');
END IF;
END IF;
END IF;
previousOTARi := my_cursorDate.otari_file;
i := i+1;
END LOOP;
RETURN solution;
EXCEPTION WHEN OTHERS THEN
raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;
/
您的程序存在一些结构性问题。最紧迫的问题是 "open and close cursor statement are commented because i'm debugging the code"。因为 open 在注释中 FETCH 失败并带有无效游标 - fetch 需要打开游标。您声称错误是在游标 FOR 循环上发出的。我想那是在您评论开放之前。游标 FOR 为游标发出一个打开。其中,如果游标打开,则抛出无效游标。您不能在打开的游标上使用游标 FOR。因此,您要么打开游标,处理第一行(获取),然后关闭游标,然后输入 FOR。退出循环后不要关闭游标。
您在嵌套 if 结构中存在逻辑问题。
IF cursorDate%FOUND THEN -- El cursor contiene info, sino %NOTFOUND
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- Dentro2!');
IF cursorDate%ROWCOUNT != 0 THEN
DBMS_OUTPUT.PUT_LINE ('OBTAIN_DATE_FIN_ABSENT -- cursor NO vacío!');
ELSE
"if cursorDate%Rowcount != 0" 将始终 return 为真。游标属性 %rowcount returns 从游标中获取的行数。如果最后一次提取 return 一行,属性 %Found returns 为真。因为这里 %Rowcount 是从属的 %Found 意味着它永远不会 return 小于 1。
另一个显而易见的语句是
IF v2(i-1) = NULL THEN
它有两个问题。首先,你的变量 i 被初始化为 1,所以上面的语句然后读取 v2(0)。这是无效的,pl/sql 中的索引值以 1 开头。一旦正确,结果语句将永远不会为真。您不能将关系运算符与 Null 一起使用;这样做的结果始终为 Null。你需要 "v2(i) is Null"。
如果您仍然有问题,请解决这些问题 post 另一个问题。