【问题标题】:Oracle Error "Ora-06502 PL/SQL: numaric or value error: invalid LOB locate"Oracle 错误“Ora-06502 PL/SQL:数字或值错误:无效的 LOB 定位”
【发布时间】:2015-07-22 09:41:04
【问题描述】:

当两个用户尝试同时提交时,我收到此 Oracle 错误 Ora-06502 PL/SQL: numeric or value error: invalid LOB locate

我实际上很努力地解决了这个问题,但我找不到解决方案。

详情请查看代码。

PROCEDURE CHECK_POP_DATA_PCC(RETURN_STATUS IN OUT NUMBER) IS LAST BOOLEAN;

 REC_NUMBER NUMBER;

 MESS_CTR NUMBER;

 NO_DETAIL EXCEPTION;

 SWF_FAIL EXCEPTION;

 USA_STATUS NUMBER;

 TEXT_STATUS NUMBER;

 FIRST_ROUND NUMBER;

 OERR NUMBER;

 FILE_NAME VARCHAR2(100);

 FILE_NAME1 VARCHAR2(100);

 FILE_NAME2 VARCHAR2(100);

 FILE_DIR VARCHAR2(100);

 PRINT_ERR EXCEPTION;

 PRINT_ERR1 EXCEPTION;

 MESS_TEXT VARCHAR2(1000);

 CTR NUMBER;

 LEN NUMBER;

 SUB NUMBER;

 OPEN_TYPE NUMBER;

 J NUMBER;

 STR1 VARCHAR2(100);

 STR2 VARCHAR2(100);

 SPC NUMBER;

 ESCP VARCHAR2(512);

 FIRST_SEQ NUMBER;

 REM NUMBER;

 CLOSE_TYPE NUMBER;

 SWF_ADD VARCHAR2(100);

 SWF_PASS VARCHAR2(100);

 SWF_UNAME VARCHAR2(100);

 COMP_FILE TEXT_IO.FILE_TYPE;

 FIRST_FILE TEXT_IO.FILE_TYPE;

 SECOND_FILE TEXT_IO.FILE_TYPE;

 cur_hdl integer;

 rows_p integer;

 tmp_chr VARCHAR2(2);

 SWF_FTP_COM VARCHAR2(100);

 File_status NUMBER;

 ret_sta NUMBER;

 key_all_data CLOB;

 RTGS_IPADD VARCHAR2(100);

 RTGS_FLA NUMBER (1,0);

 RTGS_UNAME VARCHAR2(100);

 RTGS_PASS VARCHAR2(100);

 IS_SEC NUMBER ;


CURSOR C2 IS
SELECT MESS_TYPE_CODE,
       SEQ_NUM,
       FROM_SWF_CODE,
       TO_SWF_CODE,
       PRTY_CODE
FROM SWF_MESS
WHERE BRA_CODE = :SYS.BRA_CODE
  AND REF_TYPE = :SYS.REF_TYPE
  AND REF_YEAR = :SYS.REF_YEAR
  AND REF_NUM = :SYS.REF_NUM
  AND NVL(FILE_NUM,0) = :SYS.FILE_NUM
  AND MESS_STA_CODE NOT IN (1,
                            2,
                            3,
                            5,
                            6,
                            7,
                            8);

 BEGIN RET_STA := 0;


SELECT SWF_IPADDRESS,
       SWF_USERNAME,
       SWF_PASSWORD,
       nvl(SWF_EOL_CHR,'CHR(10)'),
       FTP_COM,
       RTGS_IPADDRESS,
       RTGS_FLAG,
       RTGS_USERNAME,
       RTGS_PASSWORD,
       IS_SECURE INTO SWF_ADD,
                      SWF_UNAME,
                      SWF_PASS,
                      :TIT.EOL_SWF,
                           SWF_FTP_COM,
                           RTGS_IPADD,
                           RTGS_FLA,
                           RTGS_UNAME,
                           RTGS_PASS,
                           IS_SEC ---SHAZA(BANK/27/4540)

FROM web_par
WHERE app_ipaddress = nvl(:GLOBAL.APP_IPADDRESS,'0.0.0.0') ;

 /* *************************************** */ FIRST_ROUND := 0;

 RETURN_STATUS := 0;

 FIRST_SEQ := 0;

 key_all_data := '';

 IF :GLOBAL.BRA_BRA_CODE = :GLOBAL.BAN_HO_REG_CODE THEN GO_BLOCK('SYS');

 FIRST_RECORD;

 LAST := FALSE;

 WHILE NOT LAST LOOP IF :SYS.FLAG = 1 THEN
FOR C2REC IN C2 LOOP A07SWF00(:SYS.BRA_CODE,:SYS.REF_TYPE,:SYS.REF_YEAR,:SYS.REF_NUM, C2REC.MESS_TYPE_CODE,C2REC.SEQ_NUM,RETURN_STATUS);

 IF RETURN_STATUS = 0 THEN
COMMIT;

 CHECK_FRM_STATS;

 ELSE RAISE SWF_FAIL;

 END IF;

 END LOOP;

 END IF;

 IF :SYSTEM.LAST_RECORD = 'TRUE' THEN LAST := TRUE;

 ELSE NEXT_RECORD;

 END IF;

 END LOOP;

 END IF;

 /*****************************************************/ GO_BLOCK('SYS');

 FIRST_RECORD;

 LAST := FALSE;

 WHILE NOT LAST LOOP IF :SYS.FLAG = 1 THEN key_all_data := '';

 FIRST_ROUND := 0;


SELECT SWF_SEQ.NEXTVAL INTO :KEY.SWF_SEQ
FROM DUAL;

 IF FIRST_SEQ = 0 THEN :KEY.FROM_SWF_SEQ := :KEY.SWF_SEQ;

 FIRST_SEQ := 1;

 END IF;


FOR C2REC IN C2 LOOP /*******************************/
SELECT COUNT(*) INTO MESS_CTR
FROM SWF_DETL
WHERE BRA_CODE = :SYS.BRA_CODE
  AND REF_TYPE = :SYS.REF_TYPE
  AND REF_YEAR = :SYS.REF_YEAR
  AND REF_NUM = :SYS.REF_NUM
  AND MESS_TYPE_CODE = C2REC.MESS_TYPE_CODE
  AND SEQ_NUM = C2REC.SEQ_NUM;

 IF MESS_CTR > 0 THEN CHECK_MESS_USA(:SYS.BRA_CODE,:SYS.REF_TYPE,:SYS.REF_YEAR, :SYS.REF_NUM,C2REC.MESS_TYPE_CODE,C2REC.SEQ_NUM, USA_STATUS);

 IF USA_STATUS = 0 THEN CHECK_MESS_TEXT(C2REC.MESS_TYPE_CODE,C2REC.SEQ_NUM, C2REC.FROM_SWF_CODE,C2REC.TO_SWF_CODE, C2REC.PRTY_CODE,TEXT_STATUS);

 IF TEXT_STATUS = 0 THEN A07SWF60 ( :sys.BRA_CODE, :sys.REF_TYPE, :sys.REF_YEAR, :sys.REF_NUM, c2rec.MESS_TYPE_CODE, c2rec.SEQ_NUM, :global.WST_TELL_ID, :key.SWF_SEQ, :GLOBAL.CLI_BANK_DATE, :SYS.ALL_DATA, RETURN_STATUS);

 IF RETURN_STATUS <> 0 THEN RETURN_STATUS := -SQLCODE;

 RETURN;

 END IF;


UPDATE SWF_MESS
SET RTGS_FLAG = :SYS.RTGS_FLAG
WHERE BRA_CODE = :SYS.BRA_CODE
  AND REF_TYPE = :SYS.REF_TYPE
  AND REF_YEAR = :SYS.REF_YEAR
  AND REF_NUM = :SYS.REF_NUM
  AND MESS_TYPE_CODE = C2REC.MESS_TYPE_CODE
  AND SEQ_NUM = C2REC.SEQ_NUM;

 IF FIRST_ROUND = 0 THEN dbms_lob.createtemporary(key_all_data, TRUE);

 dbms_lob.open(key_all_data, 1);

 dbms_lob.append(key_all_data,:SYS.ALL_DATA);

 FIRST_ROUND := 1;

 ELSE ESCP := '';

 IF :SYS.PRE_LEN <> 0 THEN REM := :SYS.PRE_LEN/512;

 IF (REM - TRUNC(REM)) <> 0 THEN SPC := 512 - (:SYS.PRE_LEN - (TRUNC(REM) * 512));


FOR I IN 1..SPC LOOP ESCP := ESCP||CHR(32);

 END LOOP;

 END IF;

 ELSE ESCP := '';

 END IF;

 /*********************************************/ dbms_lob.append(key_all_data,ESCP);

 dbms_lob.append(key_all_data,:SYS.ALL_DATA);

 END IF;

 ELSE RETURN_STATUS := TEXT_STATUS;

 RAISE SWF_FAIL;

 END IF;

 ELSE RETURN_STATUS := USA_STATUS;

 RAISE SWF_FAIL;

 END IF;

 ELSE RAISE NO_DETAIL;

 END IF;

 END LOOP;

 IF :TIT.INP_SECU_CODE = 2 THEN FILE_NAME := 'OUT'||LPAD(TO_CHAR(:KEY.SWF_SEQ),5,'0')||'.ABI';

 ELSE --alliance
 FILE_NAME := 'OUT'||LPAD(TO_CHAR(:KEY.SWF_SEQ),5,'0')||'.MSG';

 END IF;

 --   FILE_DIR  := '/u/oracle/dev/spool';
 --LEN := NVL(LENGTH(key_all_data), 0);
 LEN := NVL(dbms_lob.getlength(key_all_data),0);--

CTR := LEN / 1000 ;

 IF CTR <= 1 THEN CTR := 1;

 SUB := LEN;

 ELSE IF (CTR - TRUNC(CTR)) <> 0 THEN CTR := TRUNC(CTR) + 1;

 END IF ;

 SUB := 1000;

 END IF;

 OPEN_TYPE := 1;

 J := 1;

 IF :tit.eol_swf <> 'CHR(13)||CHR(10)' THEN BEGIN key_all_data := replace(key_all_data,chr(13)||chr(10),chr(substr(:tit.eol_swf,5,2)));

 exception WHEN others THEN NULL;

 END;

 END IF;

 comp_file := TEXT_IO.FOPEN(NAME_IN('GLOBAL.PRINT_PATH')||FILE_NAME, 'W');


FOR I IN 1..CTR LOOP MESS_TEXT := dbms_lob.substr(key_all_data,1000,j);--

TEXT_IO.PUT (comp_file, mess_text);

 OPEN_TYPE := 2;

 IF return_status = 0 THEN J := J + 1000;

 ELSIF RETURN_STATUS IN(1196,
                        1197,
                        1198,
                        1199) THEN RAISE PRINT_ERR;

 ELSE RAISE PRINT_ERR1;

 END IF ;

 END LOOP;

 /************** CLOSING THE FILE *****************************/ IF :SYS.LEN <> 0 THEN REM := :SYS.LEN/512;

 IF (REM - TRUNC(REM)) <> 0 THEN SPC := 512 - (:SYS.LEN - (TRUNC(REM) * 512));

 CLOSE_TYPE := 1;

 ELSE CLOSE_TYPE := 3;

 END IF;

 ELSE CLOSE_TYPE := 3;

 END IF;

 OERR := 0;

 IF CLOSE_TYPE = 1 THEN
FOR I IN 1..SPC LOOP ESCP := CHR(32);

 Text_IO.PUT(COMP_FILE,ESCP);

 END LOOP;

 END IF;

 TEXT_IO.FCLOSE(comp_file);

 RETURN_STATUS := OERR;

 IF OERR <> 0 THEN IF OERR = 1199 THEN RAISE PRINT_ERR;

 ELSE RAISE PRINT_ERR1;

 END IF ;

 END IF;

 IF NVL(RTGS_FLA,0)=2
AND :SYS.RTGS_FLAG=1 THEN send_swf_mess(FILE_NAME, RTGS_IPADD, RTGS_UNAME, RTGS_PASS, SWF_FTP_COM,IS_SEC, RET_STA);

 ELSE send_swf_mess(FILE_NAME, SWF_ADD, SWF_UNAME, SWF_PASS, SWF_FTP_COM, IS_SEC, RET_STA);

 END IF;

 :SYS.LEN := 0;

 GO_BLOCK('SYS');

 END IF;

 IF :SYSTEM.LAST_RECORD = 'TRUE' THEN LAST := TRUE;

 ELSE NEXT_RECORD;

 END IF;

 END LOOP;

 dbms_lob.close(key_all_data);

 FIRST_RECORD;

 :KEY.TO_SWF_SEQ := :KEY.SWF_SEQ;

 EXCEPTION WHEN FORM_TRIGGER_FAILURE THEN RAISE FORM_TRIGGER_FAILURE ;

 WHEN NO_DETAIL THEN :TIT.COMMIT := 1;

 ROLLDATA;

 RETURN_STATUS := 374;

 :GLOBAL.TAB_ENT := '0374';

 DISPLAY_MSG;

 RETURN;

 WHEN SWF_FAIL THEN :TIT.COMMIT := 1;

 ROLLDATA;

 display_err(return_status);

 RETURN;

 WHEN PRINT_ERR THEN ROLLDATA;

 :global.tab_ent :=return_status ;

 display_msg ;

 :TIT.COMMIT := 1 ;

 WHEN PRINT_ERR1 THEN ROLLDATA;

 display_err(return_status);

 :TIT.COMMIT := 1 ;

 WHEN OTHERS THEN :TIT.COMMIT := 1;

 ROLLDATA;

 RETURN_STATUS := -SQLCODE;

 display_err(return_status);

 RETURN;

 END;

这是向其中一位用户显示的错误消息的屏幕截图,而另一位用户则看到操作成功

【问题讨论】:

  • 这需要大量代码;你已经做了什么调试?最初的想法是key_all_data := ... 分配看起来很可疑,因为它们会与临时 CLOB 冲突,确定吗?在过程中间提交和回滚也让我抽搐,但不确定它是否会导致此类问题。
  • @Elyasin - 我认为你需要找到一个不同的美化者;你真的认为这更容易阅读吗?
  • 我真的试过了。但是我在网上找不到更好的。对我来说更容易阅读。你认为我应该回滚吗?请对此评论投赞成票,我将恢复更改。很抱歉。
  • @AlexPoole - 我和你一样认为这样的任务看起来很可疑,但我在谈论另一个案例。假设数据分配有问题,所以无论如何它都不起作用。在正常情况下它也可以正常工作,除了提到的情况。

标签: oracle plsql lob


【解决方案1】:

如果您的 C2 光标没有找到任何内容,您将收到该错误; CLOB 永远不会打开,因为您没有进入循环,但您仍然执行dbms_lob.close,这将引发 ORA-22275 错误:

DECLARE
  key_all_data CLOB;
BEGIN
  dbms_lob.close(key_all_data);
END;
/

ORA-06502: PL/SQL: numeric or value error: invalid LOB locator specified: ORA-22275

您实际上不需要打开临时 CLOB,这意味着您也不需要关闭它;但无论哪种方式,您都应该释放它。所以你可以删除该行:

dbms_lob.open(key_all_data, 1);

并改变:

dbms_lob.close(key_all_data);

到:

if dbms_lob.istemporary(key_all_data) = 1 then
  dbms_lob.freetemporary(key_all_data);
end if;

如果您想保留open,那么也要测试关闭部分:

if dbms_lob.istemporary(key_all_data) = 1 then
  if dbms_lob.isopen(key_all_data) = 1 then
    dbms_lob.close(key_all_data);
  end if;
  dbms_lob.freetemporary(key_all_data);
end if;

您可能会认为,如果您创建了临时 CLOB 并打开它,那么它将是打开的,因此可以关闭;但是这个:

key_all_data := replace(...);

... 正在将一个临时 CLOB 替换为另一个未明确打开的临时 CLOB。您可以查看 istemporaryisopen 值以了解发生了什么。你可以看看dbms_lob.fragment_replace等,或者跳过open/close,别担心......

不清楚对这个过程的调用是否改变了下一个调用在游标中看到的内容(因为update 似乎没有做任何事情)但是这个调用的表单或其他东西可能会做更多的工作确实如此。

可能还有很多其他问题和 cmets - exception when others then null 作为一个非常糟糕的主意跳出来 - 但他们有点跑题了。

【讨论】:

  • 你是对的,这个问题在更换LOB关闭后解决,这就是为什么第二个用户出现这个错误..光标C2没有找到任何东西。我只是放了一些痕迹来找到游标没有为第二个用户获取数据,但不幸的是,你更快地发现了问题。非常感谢您也得到了解决方案。
【解决方案2】:

我认为您正在尝试将空值附加到 clob 变量。

declare
 key_all_data clob := 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
 v varchar2(10);
begin
  begin 
  dbms_lob.append(key_all_data,v); -- exception 
  exception when others then
   dbms_output.put_line(sqlerrm);
  end;

 for rec in ( select empty_clob() c from dual) loop  -- run - ok 
    dbms_lob.append(key_all_data,rec.c); 
 end loop;

   begin 
 for rec in ( select to_clob(null) c from dual) loop -- exception
    dbms_lob.append(key_all_data,rec.c);
 end loop;
  exception when others then
   dbms_output.put_line(sqlerrm);
  end;
end;

【讨论】:

  • 一个用户成功,另一个用户不成功。很高兴看到这会导致分配 NULL 值。
  • 我在 11.2.0.4 上启动了我的示例
  • 捕获此异常并在其他人之后重新抛出异常 raise_application_error(-20001,SQLERRM||chr(10)||dbms_utility.format_error_backtrace);结束;
  • 我很确定问题不是由空值引起的。当我由一个用户尝试相同的情况时,它从未发生过,我还提到了具体情况,唯一的情况是我得到了这个错误。
猜你喜欢
  • 2016-12-18
  • 2014-12-30
  • 1970-01-01
  • 1970-01-01
  • 2014-04-25
  • 1970-01-01
  • 2021-12-26
  • 1970-01-01
相关资源
最近更新 更多