Oracle 无法在INTO list中混合使用单行和多行(批量)。proc中出现错误

Oracle 无法在INTO list中混合使用单行和多行(批量)。proc中出现错误,oracle,stored-procedures,plsql,Oracle,Stored Procedures,Plsql,已编译过程ATCHMNT\u ERR\u FILEID 错误:检查过程的编译器日志错误 RDBSTAGE.ATCHMNT\u ERR\u文件ID: 行/列错误 11/40 PLS-00497:不能在列表中混合单行和多行批量 14/5 PL/SQL:忽略语句 14/31 PLS-00302:必须声明组件“计数” PLS-00497:无法在列表中混合单行和多行批量 BULK COLLECT INTO是用于从查询填充PL/SQL集合的语法。但您的代码正在填充标量单行变量 14/31 PLS-00302

已编译过程ATCHMNT\u ERR\u FILEID

错误:检查过程的编译器日志错误 RDBSTAGE.ATCHMNT\u ERR\u文件ID: 行/列错误

11/40 PLS-00497:不能在列表中混合单行和多行批量 14/5 PL/SQL:忽略语句 14/31 PLS-00302:必须声明组件“计数”

PLS-00497:无法在列表中混合单行和多行批量

BULK COLLECT INTO是用于从查询填充PL/SQL集合的语法。但您的代码正在填充标量单行变量

14/31 PLS-00302:必须声明组件“计数”

I_ATCHMNT_ERR.COUNT无效,因为COUNT仅适用于集合I_ATCHMNT_ERR为标量

要解决此问题,您需要定义和使用集合类型。大概是这样的:

CREATE OR REPLACE PROCEDURE RDBSTAGE.ATCHMNT_ERR_FILEID AUTHID CURRENT_USER
IS
  CURSOR cv_atchtab IS
    SELECT * FROM ATTACHMENT_ERROR;
  I_ATCHMNT_ERR cv_atchtab%ROWTYPE;
  V_FILE_ID VARCHAR2(40);
BEGIN
  OPEN cv_atchtab;
  LOOP
    FETCH cv_atchtab BULK COLLECT INTO I_ATCHMNT_ERR;
    EXIT WHEN cv_atchtab%NOTFOUND;
    FOR i IN 1..I_ATCHMNT_ERR.COUNT
    LOOP
      SELECT FILE_ID BULK COLLECT
      INTO V_FILE_ID
      FROM ATTACHMENT_CLAIM t1
      WHERE t1.CLAIM_TCN_ID=I_ATCHMNT_ERR(i).CLAIM_TCN_ID;
      UPDATE ATTACHMENT_ERROR
      SET FILE_ID          = V_FILE_ID
      WHERE t1.CLAIM_TCN_ID=I_ATCHMNT_ERR.CLAIM_TCN_ID;
    END LOOP;

  END LOOP;    
  CLOSE cv_atchtab;    
END;

END ATCHMNT_ERR_FILEID;

/
SHOW ERRORS 
这是与我对数据模型的猜测相反的

Oracle文档内容全面、在线且免费。PL/SQL指南有一整章关于集合和记录,我建议您阅读


另一方面,在PL/SQL中,具有类似这样的单行语句的嵌套循环通常是一个危险信号。它们效率很低,速度也很慢。SQL是一种基于集合的语言,我们应该尽可能使用SQL解决问题,最好是使用一个基于集合的语句。如果这段代码是为了生产而不是作为作业,你应该考虑重新写一个更具表现力的方式。

为了将来的参考,请编辑你的问题,包括附加信息或澄清。这是一个学习练习吗?或者这是生产代码?@boneist-我希望这不是生产代码。我已经运行了新的更改,但得到了以下内容A-00904:t1。声明\u TCN\u ID无效标识当前获取此行/COL错误--------------------------------------------25/21 PLS-00642:SQL语句中不允许使用本地集合类型我使用了Oracle数据库12cSo在我以前的代码版本中,我也将V_FILE_ID作为一个集合。但是没有更改UPDATE语句中的SET子句。这就是PLS-00642错误的原因。我通过将V_FILE_ID恢复为标量并在填充大容量COLLECT子句时将其删除,解决了这个问题。我没有发现这个错误,因为我最初的测试与您的场景不完全相同。所以我也做了您应该做的事情,并提供了一个完整的工作测试用例。找到我的。
CREATE OR REPLACE PROCEDURE ATCHMNT_ERR_FILEID
IS
  CURSOR cv_atchtab IS
    SELECT * FROM ATTACHMENT_ERROR;

  type ATCHMNT_ERR_nt is table of cv_atchtab%ROWTYPE;
  I_ATCHMNT_ERR ATCHMNT_ERR_nt;

  V_FILE_ID VARCHAR2(40);
BEGIN
  OPEN cv_atchtab;
  LOOP
    FETCH cv_atchtab BULK COLLECT INTO I_ATCHMNT_ERR; -- collection type
    EXIT WHEN I_ATCHMNT_ERR.COUNT = 0; -- changed this

    FOR i IN 1..I_ATCHMNT_ERR.COUNT
    LOOP
      SELECT FILE_ID 
      INTO V_FILE_ID  -- scalar type
      FROM ATTACHMENT_CLAIM t1
      WHERE t1.CLAIM_TCN_ID = I_ATCHMNT_ERR(i).CLAIM_TCN_ID;

      UPDATE ATTACHMENT_ERROR t2 -- changed this
      SET FILE_ID = V_FILE_ID
      WHERE t2.CLAIM_TCN_ID = I_ATCHMNT_ERR(i).CLAIM_TCN_ID;  -- changed this
    END LOOP;

  END LOOP;    
  CLOSE cv_atchtab; 

END ATCHMNT_ERR_FILEID;