我正试图为数据类型为CLOB
的列创建更新语句。
为此,我要从表中获取XML并在oracle控制台中编写它以供以后使用。
对于某些数据,它工作正常。
对于某些人,我得到
异常1:CREATE_UPDATE_XML_QUERY('600264','700009');
-ORA-06502:PL / SQL:数字或值错误
我更改了V_XML
的数据类型,V_BLOCK
无效
PROCEDURE CREATE_UPDATE_XML_QUERY
(
MY_ID NUMBER,
MY_ID2 NUMBER
) AS
V_SCREEN_VERSION NUMBER;
V_XML_ID NUMBER;
V_CNT NUMBER;
V_XML CLOB);
V_BLOCK CLOB;
BEGIN
SELECT XML,XMLID INTO V_XML,V_XML_ID
FROM XML_TABLE WHERE ENC_ID = MY_ID AND SCREEN_ID = MY_ID2 ; ----getting excption
V_BLOCK :=
'
SET SERVEROUTPUT ON;
DECLARE
V_XML CLOB ;
BEGIN
';
V_BLOCK := V_BLOCK||'V_XML := '''||V_XML||''';';
V_BLOCK := V_BLOCK||'
UPDATE XML_TABLE SET XML = '||'V_XML'||'
WHERE ENC_ID = '||MY_ID||' AND ENC_TYPE = ''P'' AND SCREEN_ID = '||MY_ID2||' AND XMLID = '||V_XML_ID||';
--DBMS_OUTPUT.PUT_LINE(''V_XML =>''||V_XML);
DBMS_OUTPUT.PUT_LINE(''ROWCOUNT =>''||SQL%ROWCOUNT);
END;
/';
DBMS_OUTPUT.PUT_LINE('--Printing Annomous Block the XML :->>');
DBMS_OUTPUT.PUT_LINE(V_BLOCK);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Exception1 : UPDATE_SCREEN_MASTER_XML('''||MY_ID||''','''||MY_ID2||''','''||V_XML_ID||'''); --'||SQLERRM);--'||SQLERRM);
END CREATE_UPDATE_XML_QUERY;
如何避免错误。
是因为我的XML
太大了。
答案 0 :(得分:2)
好吧,我想出一个测试用例来重现此问题(Oracle 12.2.0.1),对了,问题不在于DBMS_OUTPUT行。
declare
v_clob clob;
xmlid number;
begin
-- initialize clob and make clob a string of length 32768
dbms_lob.createtemporary(v_clob, true);
for i in 1..32768 loop
v_clob := v_clob || 'x';
end loop;
dbms_output.put_line(length(v_clob));
-- testing:
v_clob := v_clob || 'x'; -- appending a varchar2 works fine
v_clob := v_clob || xmlid; -- appending a number gives ORA-06502
v_clob := v_clob || 'x' || xmlid; -- appending a string+number still gives ORA-06502
v_clob := v_clob || to_clob(xmlid); -- works fine
dbms_lob.append(v_clob, 'x' || xmlid); -- also works fine
dbms_output.put_line(length(v_clob));
dbms_output.put_line(substr(v_clob,1,32767));
end;
/
问题似乎是,当您用管道将字符串连接在一起时,如果其中一个超过32k,Oracle可以将2个Clob附加在一起,并且可以将varchar2隐式转换为Clob并附加它们。但是,如果您尝试将数字附加到超过32k的Clob中,它将失败。它了解如何附加varchar2和number,clob和clob以及clob和varchar2。但这似乎无法自动找出数字-> varchar2-> clob。您可以通过将字符串包装在to_clob()
中来解决该问题,从而避免Oracle隐式转换带来的问题。
答案 1 :(得分:1)
在何处出现错误取决于表的XML
CLOB值的长度。
如果XML大于32k,则您将在代码中的第27行看到错误,从尝试将一个连接到一个数字(如@kfinity所示)到CLOB上; in the documentation尚未解释的行为,但可能与隐式转换有关,因为只是使用varchar2
字符串to_char(MY_ID)
(或to_clob(MY_ID)
)显式转换了数字。
如果XML小于但接近32k,那么您会刮掉它,但是V_BLOCK
CLOB最终仍然大于32k,那么在第39行仍会以{{ 1}}无法解决这个问题。
您可以通过在数字变量周围使用dbms_output
或使用to_char()
而不是串联来避免第一个问题:
dbms_lob.append
只要XML值包含换行符,就可以避免第二个问题,方法是将CLOB分成几行as shown here,但要稍作修改以处理空行。带有附加变量声明为:
...
V_BLOCK :=
'
SET SERVEROUTPUT ON;
DECLARE
V_XML CLOB ;
BEGIN
';
dbms_lob.append(V_BLOCK, 'V_XML := '''||V_XML||''';');
dbms_lob.append(V_BLOCK, '
UPDATE XML_TABLE SET XML = '||'V_XML'||'
WHERE ENC_ID = '||MY_ID||' AND ENC_TYPE = ''P'' AND SCREEN_ID = '||MY_ID2||' AND XMLID = '||V_XML_ID||';
--DBMS_OUTPUT.PUT_LINE(''V_XML =>''||V_XML);
DBMS_OUTPUT.PUT_LINE(''ROWCOUNT =>''||SQL%ROWCOUNT);
END;
/');
...
然后而不是:
V_BUFFER VARCHAR2(32767);
V_AMOUNT PLS_INTEGER;
V_POS PLS_INTEGER := 1;
您可以这样做:
DBMS_OUTPUT.PUT_LINE(V_BLOCK);
@VinayakDwivedi编辑后添加了要使用的功能:
WHILE V_POS < length(V_BLOCK) LOOP
-- read to next newline if there is one, rest of CLOB if not
IF dbms_lob.instr(V_BLOCK, chr(10), V_POS) > 0 THEN
V_AMOUNT := dbms_lob.instr(V_BLOCK, chr(10), V_POS) - V_POS;
IF V_AMOUNT = 0 THEN
V_BUFFER := null; -- first character is a new line (i.e. a blank line)
ELSE
dbms_lob.read(V_BLOCK, V_AMOUNT, V_POS, V_BUFFER);
END IF;
V_POS := V_POS + V_AMOUNT + 1; -- skip newline character
ELSE
V_AMOUNT := 32767;
dbms_lob.read(V_BLOCK, V_AMOUNT, V_POS, V_BUFFER);
V_POS := V_POS + V_AMOUNT;
END IF;
DBMS_OUTPUT.PUT_LINE(V_BUFFER);
END LOOP;
...但是这将导致每10000个字符额外的换行符。
但是,值得注意的是,您在其中生成的PL / SQL块以如下行结尾:
PROCEDURE print_clob_to_output (p_clob IN CLOB)
IS
v_offset NUMBER := 1;
v_chunk_size NUMBER := 10000;
BEGIN
LOOP
EXIT WHEN v_offset > DBMS_LOB.getlength (p_clob);
DBMS_OUTPUT.put_line (
DBMS_LOB.SUBSTR (p_clob, v_chunk_size, v_offset));
v_offset := v_offset + v_chunk_size;
END LOOP;
END print_clob_to_output;
,如果运行了该生成的代码,并且原始XML大于32k,也会出错。确实,生成的代码也需要分解才能以块的形式重建您的CLOB-即一个循环,一次要占用32k并连接/附加这些块以重新构成完整值。它在每行的开头也有空格,因此V_XML := '<original xml from table>';
等,更重要的是最后的DECLARE
不在其各自行的开头,这在尝试按以下方式运行它时也会引起问题-是。
答案 2 :(得分:0)
签出: https://www.techonthenet.com/oracle/errors/ora06502.php 这表明该错误可能有3种可能的原因
在不了解更多上下文的情况下,实际上不可能确定其中哪个是您的问题。
希望这会有所帮助!