更新过程中的 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】:

这个错误实际上是正确的,但它相当微妙。名字不一样。声明opencurrent of 有一个名称; fetchclose 有一些非常细微的不同。如果您在浏览器中进行查找并搜索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', 呈现为с。因此,您将恰好看起来相同的拉丁字符和西里尔字符混合在一起。

fetchclose 语句中重新输入变量名,它就会编译成功。 (但最好不要在system 架构中......)

【讨论】:

感激之情无法形容! 亚历克斯,你是怎么找到它的。??!!酷:)

以上是关于更新过程中的 Oracle 游标。必须声明标识符的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Oracle PL/SQL 过程的开始部分之后声明游标

c# 调用Oracle存储过程 PLS-00201:必须声明标识符

Oracle:在游标声明中使用自定义函数

mysql使用游标遍历数据进行批量针对性更新数据,急求mysql大神解答

Oracle存储过程与游标

Oracle 错误 PLS-00323:子程序或游标在包规范中声明,必须在包主体中定义