更新过程中的 Oracle 游标。必须声明标识符
Posted
技术标签:
【中文标题】更新过程中的 Oracle 游标。必须声明标识符【英文标题】:Oracle cursor in update procedure. Identifier must be declared 【发布时间】:2014-03-01 07:55:12 【问题描述】:我正在编写用于在 TEST_SENDING_BOX_TABLE 中插入(更新)REAL_START_DATE 的存储过程,但我的光标“标识符必须声明为异常”
PROCEDURE IN_SENDBOX_WORK_REALSTART (id_work TEST_SENDING_BOX_WORK.ID_SENDING_BOX_WORK%TYPE, real_start TEST_SENDING_BOX_WORK.REAL_START_DATE%TYPE) IS
CURSOR cur_work (id_w number) is
SELECT * FROM TEST_SENDING_BOX_WORK
WHERE ID_SENDING_BOX_WORK=id_w
FOR UPDATE OF REAL_START_DATE;
rec_to_mod TEST_SENDING_BOX_WORK%ROWTYPE;
BEGIN
open cur_work(id_work);
fetch сur_work into rec_to_mod;//Error(83,10): PLS-00201: identifier 'СUR_WORK' must be declared
UPDATE TEST_SENDING_BOX_WORK //Error(87,3): PL/SQL: SQL Statement ignored
SET REAL_START_DATE=real_start
WHERE CURRENT OF cur_work;
close сur_work; //Error(87,10): PLS-00201: identifier 'СUR_WORK' must be declared
END IN_SENDBOX_WORK_REALSTART;
然而,这个类似的过程完美无缺。
PROCEDURE IN_or_UP_SENDBOX_DEMOUNTDATE(id_sendbox TEST_SENDING_BOX_HISTORY.ID_SENDING_BOX%TYPE, p_demount TEST_SENDING_BOX_HISTORY.DEMOUNT_DATE%TYPE) IS
cursor send_box (id_sendbox number) is
SELECT * FROM TEST_SENDING_BOX_HISTORY
WHERE ID_SENDING_BOX=id_sendbox
FOR UPDATE OF DEMOUNT_DATE;
rec_to_mod TEST_SENDING_BOX_HISTORY%ROWTYPE;
BEGIN
open send_box(id_sendbox);
fetch send_box into rec_to_mod;
UPDATE TEST_SENDING_BOX_HISTORY
SET DEMOUNT_DATE=p_demount
where CURRENT OF send_box;
close send_box;
END IN_or_UP_SENDBOX_DEMOUNTDATE;
包 TEST_DB_MOD_PKG
create or replace PACKAGE TEST_DB_MOD_PKG is
PROCEDURE INSERT_OBJ (p_idobj TEST_OBJ.ID_OBJ%TYPE, p_idobjtype TEST_OBJ.OBJ_KIND%TYPE);
PROCEDURE INSERT_SENDBOX (p_idsendingbox TEST_SENDING_BOX.ID_SENDING_BOX%TYPE, p_idsendboxmodel TEST_SENDING_BOX.ID_SENDING_BOX_MODEL%TYPE,
p_dateofman TEST_SENDING_BOX.DATE_OF_MANUFACTURE%TYPE,p_serialnum TEST_SENDING_BOX.SERIAL_NUMBER%TYPE);
PROCEDURE INSERT_DEFECT(p_iddef TEST_DEFECTIVENESS.ID_DEFECTIVENESS%TYPE, p_idsendbox TEST_DEFECTIVENESS.ID_SENDING_BOX%TYPE,
p_defkind TEST_DEFECTIVENESS.DEFECTIVENESS_KIND%TYPE,p_com TEST_DEFECTIVENESS.COMMEN%TYPE,
p_start TEST_DEFECTIVENESS.START_DATE%TYPE, p_end TEST_DEFECTIVENESS.END_DATE%TYPE);
PROCEDURE INSERT_SENDBOX_HISTORY(p_idobj TEST_SENDING_BOX_HISTORY.ID_OBJECT%TYPE, p_idsendbox TEST_SENDING_BOX_HISTORY.ID_SENDING_BOX%TYPE,
p_mount TEST_SENDING_BOX_HISTORY.MOUNT_DATE%TYPE);
PROCEDURE INSERT_OBJ_ATTR_VAL(p_idobjattr TEST_OBJ_ATTRIBUTE_VALUE.ID_OBJ_ATTRIBUTE%TYPE, p_idobj TEST_OBJ_ATTRIBUTE_VALUE.ID_OBJ%TYPE,
p_val TEST_OBJ_ATTRIBUTE_VALUE.VAL%TYPE);
PROCEDURE INSERT_WORK_ATTR_VAL(p_idworkattr TEST_WORK_ATTRIBUTE_VALUE.ID_WORK_ATTRIBUTE%TYPE, p_idwork TEST_WORK_ATTRIBUTE_VALUE.ID_WORK%TYPE,
p_val TEST_WORK_ATTRIBUTE_VALUE.VAL%TYPE);
PROCEDURE INSERT_SENDBOX_WORK(p_idwork TEST_SENDING_BOX_WORK.ID_SENDING_BOX_WORK%TYPE, p_id TEST_SENDING_BOX_WORK.ID_SENDING_BOX%TYPE,
p_idworkkind TEST_SENDING_BOX_WORK.ID_WORK_KIND%TYPE,p_idworker TEST_SENDING_BOX_WORK.ID_WORKER%TYPE,
p_start TEST_SENDING_BOX_WORK.START_DATE%TYPE,p_end TEST_SENDING_BOX_WORK.END_DATE%TYPE);
PROCEDURE INSERT_OBJ_WORK(p_idwork TEST_OBJ_WORK.ID_OBJ_WORK%TYPE, p_id TEST_OBJ_WORK.ID_OBJ%TYPE,
p_idworkkind TEST_OBJ_WORK.ID_WORK_KIND%TYPE,p_idworker TEST_OBJ_WORK.ID_WORKER%TYPE,
p_start TEST_OBJ_WORK.START_DATE%TYPE,p_end TEST_OBJ_WORK.END_DATE%TYPE);
PROCEDURE IN_or_UP_SENDBOX_DEMOUNTDATE(id_sendbox TEST_SENDING_BOX_HISTORY.ID_SENDING_BOX%TYPE, p_demount TEST_SENDING_BOX_HISTORY.DEMOUNT_DATE%TYPE);
PROCEDURE IN_SENDBOX_WORK_REALSTART (id_work TEST_SENDING_BOX_WORK.ID_SENDING_BOX_WORK%TYPE, real_start TEST_SENDING_BOX_WORK.REAL_START_DATE%TYPE);
END;
包体测试_DB_MOD_PKG
create or replace PACKAGE BODY TEST_DB_MOD_PKG IS
PROCEDURE INSERT_OBJ (p_idobj TEST_OBJ.ID_OBJ%TYPE, p_idobjtype TEST_OBJ.OBJ_KIND%TYPE) IS
BEGIN
INSERT INTO TEST_OBJ("ID_OBJ", "OBJ_KIND") VALUES (p_idobj, p_idobjtype);
END INSERT_OBJ;
PROCEDURE INSERT_SENDBOX (p_idsendingbox TEST_SENDING_BOX.ID_SENDING_BOX%TYPE, p_idsendboxmodel TEST_SENDING_BOX.ID_SENDING_BOX_MODEL%TYPE,
p_dateofman TEST_SENDING_BOX.DATE_OF_MANUFACTURE%TYPE,p_serialnum TEST_SENDING_BOX.SERIAL_NUMBER%TYPE) IS
BEGIN
INSERT INTO TEST_SENDING_BOX (ID_SENDING_BOX, ID_SENDING_BOX_MODEL,DATE_OF_MANUFACTURE,SERIAL_NUMBER)
VALUES (p_idsendingbox , p_idsendboxmodel, p_dateofman, p_serialnum);
END INSERT_SENDBOX ;
PROCEDURE INSERT_DEFECT(p_iddef TEST_DEFECTIVENESS.ID_DEFECTIVENESS%TYPE, p_idsendbox TEST_DEFECTIVENESS.ID_SENDING_BOX%TYPE,
p_defkind TEST_DEFECTIVENESS.DEFECTIVENESS_KIND%TYPE,p_com TEST_DEFECTIVENESS.COMMEN%TYPE,
p_start TEST_DEFECTIVENESS.START_DATE%TYPE, p_end TEST_DEFECTIVENESS.END_DATE%TYPE) IS
BEGIN
INSERT INTO TEST_DEFECTIVENESS (ID_DEFECTIVENESS, ID_SENDING_BOX,DEFECTIVENESS_KIND,COMMEN,START_DATE,END_DATE)
VALUES (p_iddef , p_idsendbox, p_defkind, p_com,p_start,p_end);
END INSERT_DEFECT ;
PROCEDURE INSERT_SENDBOX_HISTORY(p_idobj TEST_SENDING_BOX_HISTORY.ID_OBJECT%TYPE, p_idsendbox TEST_SENDING_BOX_HISTORY.ID_SENDING_BOX%TYPE,
p_mount TEST_SENDING_BOX_HISTORY.MOUNT_DATE%TYPE) IS
BEGIN
INSERT INTO TEST_SENDING_BOX_HISTORY (ID_OBJECT,ID_SENDING_BOX,MOUNT_DATE)
VALUES (p_idobj, p_idsendbox,p_mount);
END INSERT_SENDBOX_HISTORY ;
PROCEDURE INSERT_OBJ_ATTR_VAL(p_idobjattr TEST_OBJ_ATTRIBUTE_VALUE.ID_OBJ_ATTRIBUTE%TYPE, p_idobj TEST_OBJ_ATTRIBUTE_VALUE.ID_OBJ%TYPE,
p_val TEST_OBJ_ATTRIBUTE_VALUE.VAL%TYPE) IS
BEGIN
INSERT INTO TEST_OBJ_ATTRIBUTE_VALUE (ID_OBJ_ATTRIBUTE,ID_OBJ,VAL)
VALUES (p_idobjattr , p_idobj,p_val);
END INSERT_OBJ_ATTR_VAL ;
PROCEDURE INSERT_WORK_ATTR_VAL(p_idworkattr TEST_WORK_ATTRIBUTE_VALUE.ID_WORK_ATTRIBUTE%TYPE, p_idwork TEST_WORK_ATTRIBUTE_VALUE.ID_WORK%TYPE,
p_val TEST_WORK_ATTRIBUTE_VALUE.VAL%TYPE) IS
BEGIN
INSERT INTO TEST_WORK_ATTRIBUTE_VALUE(ID_WORK_ATTRIBUTE,ID_WORK,VAL)
VALUES (p_idworkattr , p_idwork,p_val);
END INSERT_WORK_ATTR_VAL ;
PROCEDURE INSERT_SENDBOX_WORK(p_idwork TEST_SENDING_BOX_WORK.ID_SENDING_BOX_WORK%TYPE, p_id TEST_SENDING_BOX_WORK.ID_SENDING_BOX%TYPE,
p_idworkkind TEST_SENDING_BOX_WORK.ID_WORK_KIND%TYPE,p_idworker TEST_SENDING_BOX_WORK.ID_WORKER%TYPE,
p_start TEST_SENDING_BOX_WORK.START_DATE%TYPE,p_end TEST_SENDING_BOX_WORK.END_DATE%TYPE) IS
BEGIN
INSERT INTO TEST_SENDING_BOX_WORK(ID_SENDING_BOX_WORK,ID_SENDING_BOX,ID_WORK_KIND,ID_WORKER,START_DATE,END_DATE)
VALUES (p_idwork , p_id,p_idworkkind,p_idworker,p_start,p_end );
END INSERT_SENDBOX_WORK;
PROCEDURE INSERT_OBJ_WORK(p_idwork TEST_OBJ_WORK.ID_OBJ_WORK%TYPE, p_id TEST_OBJ_WORK.ID_OBJ%TYPE,
p_idworkkind TEST_OBJ_WORK.ID_WORK_KIND%TYPE,p_idworker TEST_OBJ_WORK.ID_WORKER%TYPE,
p_start TEST_OBJ_WORK.START_DATE%TYPE,p_end TEST_OBJ_WORK.END_DATE%TYPE) IS
BEGIN
INSERT INTO TEST_OBJ_WORK(ID_OBJ_WORK,ID_OBJ,ID_WORK_KIND,ID_WORKER,START_DATE,END_DATE)
VALUES (p_idwork , p_id,p_idworkkind,p_idworker,p_start,p_end );
END INSERT_OBJ_WORK;
PROCEDURE IN_or_UP_SENDBOX_DEMOUNTDATE(id_sendbox TEST_SENDING_BOX_HISTORY.ID_SENDING_BOX%TYPE, p_demount TEST_SENDING_BOX_HISTORY.DEMOUNT_DATE%TYPE) IS
cursor send_box (id_sendbox number) is
SELECT * FROM TEST_SENDING_BOX_HISTORY
WHERE ID_SENDING_BOX=id_sendbox
FOR UPDATE OF DEMOUNT_DATE;
rec_to_mod TEST_SENDING_BOX_HISTORY%ROWTYPE;
BEGIN
open send_box(id_sendbox);
fetch send_box into rec_to_mod;
UPDATE TEST_SENDING_BOX_HISTORY
SET DEMOUNT_DATE=p_demount
where CURRENT OF send_box;
close send_box;
END IN_or_UP_SENDBOX_DEMOUNTDATE;
PROCEDURE IN_SENDBOX_WORK_REALSTART (id_work TEST_SENDING_BOX_WORK.ID_SENDING_BOX_WORK%TYPE, real_start TEST_SENDING_BOX_WORK.REAL_START_DATE%TYPE) IS
cursor cur_work (id_work number) is
SELECT * FROM TEST_SENDING_BOX_WORK
WHERE ID_SENDING_BOX_WORK=id_work
FOR UPDATE OF REAL_START_DATE;
rec_to_mod TEST_SENDING_BOX_WORK%ROWTYPE;
BEGIN
open cur_work(id_work);
fetch сur_work into rec_to_mod;
UPDATE TEST_SENDING_BOX_WORK
SET REAL_START_DATE=real_start
WHERE CURRENT OF cur_work;
close сur_work;
END IN_SENDBOX_WORK_REALSTART;
END TEST_DB_MOD_PKG;
link to screenshot
【问题讨论】:
这两个 proc 看起来几乎和我的眼睛一模一样,除了光标名称!奇怪!! 那么,声明部分没有出现在编译器错误中? @OracleUser,不,没有错误。也许这个问题与表权限有关? 是的,在这种情况下,声明部件本身会抛出错误,这就是为什么要问.. @OracleUser,但我使用的是 SYSTEM 帐户。 SYSTEM 是否拥有所有权限? 【参考方案1】:这个错误实际上是正确的,但它相当微妙。名字不一样。声明open
和current of
有一个名称; fetch
和 close
有一些非常细微的不同。如果您在浏览器中进行查找并搜索cur_work
,您会看到这一点,特别是在它突出显示的情况下;使用您的完整代码,有 6 个匹配项而不是 10 个。
那么,有什么区别呢?以下是五个参考文献的转储:
select dump('cursor cur_work') from dual;
select dump('open cur_work') from dual;
select dump('fetch сur_work') from dual;
select dump('OF cur_work') from dual;
select dump('close сur_work') from dual;
...调整了变量名之前的空格。
Typ=96 Len=15: 99,117,114,115,111,114,32,99,117,114,95,119,111,114,107
Typ=96 Len=13: 111,112,101,110,32,99,117,114,95,119,111,114,107
Typ=96 Len=15: 102,101,116,99,104,32,209,129,117,114,95,119,111,114,107
Typ=96 Len=11: 79,70,32,99,117,114,95,119,111,114,107
Typ=96 Len=15: 99,108,111,115,101,32,209,129,117,114,95,119,111,114,107
紧跟在空格后面的字符是99
,其中三个是209,129
,另外两个是209,129
。如您所料,99
实际上是c
。另一个是according to this, U+0441
, 'Cyrillic small letter es', 呈现为с
。因此,您将恰好看起来相同的拉丁字符和西里尔字符混合在一起。
在fetch
和close
语句中重新输入变量名,它就会编译成功。 (但最好不要在system
架构中......)
【讨论】:
感激之情无法形容! 亚历克斯,你是怎么找到它的。??!!酷:)以上是关于更新过程中的 Oracle 游标。必须声明标识符的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Oracle PL/SQL 过程的开始部分之后声明游标
c# 调用Oracle存储过程 PLS-00201:必须声明标识符