一次dbms_metadata.get_ddl时报ORA-06502和ORA-06512错误

来源:这里教程网 时间:2026-03-03 18:59:08 作者:

使用dbms_metadata.get_ddl时报ORA-06502和ORA-06512错误

现象:   SQL> select dbms_metadata.get_ddl(‘TRIGGER’, ‘AFTER_CONTAINER_INSERT_TRG’, ‘JYJX’) from dual;     ERROR:     ORA-06502: PL/SQL: numeric or value error     ORA-06502: PL/SQL: numeric or value error: character string buffer too small     ORA-06512: at "SYS.DBMS_METADATA_UTIL", line 294

说明:   1)数据库版本为9.2.0.8,comptiple参数时9.2.0.0.0     2) 使用该方式获取对象的定义时,数据库中某些对象能成功,某些对象不能成功。     3)使用PLSQL的report窗口执行报同样错误     4)使用PLSQL的dbms_metadata.get_ddl报同样错误     5)使用PLSQL的查看功能可以看到该触发器的定义     6)将相同数据导入到10205数据库中后,使用同样方式获取DDL时正常。

使用6502event跟踪:   alter system set event="6502 trace name errorstack level 12" scope=spfile;

shutdown immediate;   startup

select dbms_metadata.get_ddl(‘TRIGGER’, ‘AFTER_CONTAINER_INSERT_TRG’, ‘JYJX’) from dual;

追踪文件:   *** SESSION ID 9.3) 2014-04-14 11:21:11.616          17 *** 2014-04-14 11:21:11.616          18 ksedmp: internal or fatal error          19 ORA-06502: PL/SQL: numeric or value error: character string buffer too small          20 Current SQL statement for this session:          21 SELECT VALUE(KU$) TRIGGER_T FROM SYS.KU$_TRIGGER_VIEW KU$ WHERE KU$.SCHEMA_OBJ.NAME=’AFTER_CONTAINER_INSERT_TRG’ AND KU$.SCHEMA_OBJ.OWNER_NAME=’JYJX’          22 —– PL/SQL Call Stack —–          23   object      line  object          24   handle    number  name          25 0×5bbbdaa8       294  package body SYS.DBMS_METADATA_UTIL          26 0×5bb5b42c        83  package body SYS.DBMS_XMLGEN          27 0×5bb5b42c        83  package body SYS.DBMS_XMLGEN          28 0×5bbca654       362  package body SYS.DBMS_METADATA          29 0×5bbca654       418  package body SYS.DBMS_METADATA          30 0×5bbca654       457  package body SYS.DBMS_METADATA          31 0×5bbca654       640  package body SYS.DBMS_METADATA          32 0×5bbca654      1260  package body SYS.DBMS_METADATA          33 0×5bbda7c8         1  anonymous block

可以看到报错的SQL为:   SELECT VALUE(KU$) TRIGGER_T FROM SYS.KU$_TRIGGER_VIEW KU$ WHERE KU$.SCHEMA_OBJ.NAME=’AFTER_CONTAINER_INSERT_TRG’ AND KU$.SCHEMA_OBJ.OWNER_NAME=’JYJX’    

单独执行该SQL:   SQL> SELECT VALUE(KU$) TRIGGER_T FROM SYS.KU$_TRIGGER_VIEW KU$ WHERE KU$.SCHEMA_OBJ.NAME=’AFTER_CONTAINER_INSERT_TRG’ AND KU$.SCHEMA_OBJ.OWNER_NAME=’JYJX’;     SELECT VALUE(KU$) TRIGGER_T FROM SYS.KU$_TRIGGER_VIEW KU$ WHERE KU$.SCHEMA_OBJ.NAME=’AFTER_CONTAINER_INSERT_TRG’ AND KU$.SCHEMA_OBJ.OWNER_NAME=’JYJX’                                                                                                                                                         *     ERROR at line 1:     ORA-06502: PL/SQL: numeric or value error: character string buffer too small     ORA-06512: at "SYS.DBMS_METADATA_UTIL", line 294

查看SYS.KU$_TRIGGER_VIEW的定义:   CREATE OR REPLACE VIEW SYS.KU$_TRIGGER_VIEW OF ku$_trigger_t WITH OBJECT OID (obj_num) AS     select ‘1′,’0′,              t.obj#, value(o),              (select value(bo) from ku$_schemaobj_view bo               where t.baseobject = bo.obj_num),              t.type#, t.update$, t.insert$, t.delete$, t.definition, t.whenclause,              sys.dbms_metadata_util.long2varchar(t.actionsize,                                             ‘SYS.TRIGGER$’,                                             ‘ACTION#’,                                             t.rowid),              case when t.actionsize > 4000                then                  sys.dbms_metadata_util.long2vcmax(t.actionsize,                                             ‘SYS.TRIGGER$’,                                             ‘ACTION#’,                                             t.rowid)                else NULL              end,              t.actionsize,              t.enabled, t.property, t.sys_evts       from   sys.ku$_schemaobj_view o, sys.trigger$ t       where  t.obj# = o.obj_num AND              (SYS_CONTEXT(‘USERENV’,'CURRENT_USERID’) IN (o.owner_num, 0) OR                     EXISTS ( SELECT * FROM session_roles                             WHERE role=’SELECT_CATALOG_ROLE’ ));

注意到该视图调用了函数sys.dbms_metadata_util.long2vcmax。

查看DBMS_METADATA_UTIL中的LONG2VCMAX函数:   – LONG2VCMAX: Convert a LONG column value to a VARCHAR2 and each line     –                  max length is 2000     – PARAMETERS:     –      length          – length of the LONG     –      tab             – table name     –      col             – column name     –      row             – rowid of the row     – RETURNS:     LONG value converted to VARCHAR2     –              otherwise NULL       FUNCTION long2vcmax(                     length          IN  NUMBER,                     tab             IN  VARCHAR2,                     col             IN  VARCHAR2,                     row             IN  UROWID)             RETURN sys.ku$_vcnt;     还有另外一个函数LONG2VCNT:     – LONG2VCNT: Convert a LONG column value to an array of VARCHAR2     – PARAMETERS:     –      length        – length of the LONG     –    tab        – table name     –    col        – column name     –    row        – rowid of the row     – RETURNS:    LONG value converted to array of VARCHAR2 if length > 4000     –        otherwise NULL

  FUNCTION long2vcnt(           length      IN  NUMBER,             tab        IN  VARCHAR2,         col         IN  VARCHAR2,             row         IN  UROWID)         RETURN sys.ku$_vcnt;     可以看到这两个函数的输入参数及返回值是一样的,而第二个函数,即long2vcnt是支持length大于4000的。

因此,可选择以下解决方案:   修改视图SYS.KU$_TRIGGER_VIEW的定义,替换函数long2vcmax为long2vcnt。     通过这种方法可以解决ORA-06502错误,但是该方式修改了SYS用户的内容,因此不保证不会引起其他问题。

解决方案二   在测试过程中发现将相同的数据导入到10205数据库中后,不存在问题,进一步又发现使用PLSQL的查看功能获取到     存储过程的定义后,将该定义复制到一个会话中并重新执行一遍后也可解决6502错误。     所以,解决方案就是讲存在问题的触发器定义通过PLSQL查看等方式获取出来并重新执行。

相关推荐