ORA-06502: PL/SQL: ora_sql_txt 的数字或值错误

ORA-06502: PL/SQL: numeric or value error by ora_sql_txt

我有 table 用于 ddl 日志。而在这个table中我也想看看究竟是哪段代码完成了。如何将其放入 sql_tt 列?你能提示我这个吗?

CREATE TABLE AAUDIT_DDL (
d date,
OSUSER varchar2(255),
CURRENT_USER varchar2(255),
HOST varchar2(255),
IP_ADDRESS   VARCHAR2(100 CHAR),
TERMINAL varchar2(255),
owner varchar2(30),
OBJECT_TYPE varchar2(30),
OBJECT_NAME varchar2(30),
DDL_TYPE varchar2(30),
SQL_TT varchar(100));

并触发

create or replace trigger aaudit_ddl after ddl on DATABASE

begin
if (ora_sysevent='REVOKE')
then
null; -- I do not care about REVOKE
else
insert into aaudit_ddl(d, osuser,current_user,host,ip_address,terminal,owner,OBJECT_TYPE,OBJECT_NAME,DDL_TYPE,SQL_TT)
values(
  sysdate,
  sys_context('USERENV','OS_USER') ,
  sys_context('USERENV','CURRENT_USER') ,
  sys_context('USERENV','HOST') ,
  SYS_CONTEXT('USERENV','IP_ADDRESS'),
  sys_context('USERENV','TERMINAL') ,
  ora_dict_obj_owner,
  ora_dict_obj_type,
  ora_dict_obj_name,
  ora_sysevent,
  ora_sql_txt
  );
  end if;
  end;
 /

Documentation 建议对 ora_sql_txt 采取不同的方法:作为函数期望的 IN 参数(它是一个整数,表示 PL/SQL table 中的元素数), 你应该

CREATE TABLE event_table (col VARCHAR2(2030));

DECLARE
  sql_text   ora_name_list_t;
  n          PLS_INTEGER;
  v_stmt     VARCHAR2(2000);
BEGIN
  n := ora_sql_txt(sql_text);

  FOR i IN 1..n LOOP
    v_stmt := v_stmt || sql_text(i);
  END LOOP;

  INSERT INTO event_table VALUES ('text of triggering statement: ' || v_stmt);
END;

这就是我的设置方式,效果很好。


 --Table will be created by sys user with tbs_audit as tablespace as default tablespace for audit table AUDIT_DDL

CREATE TABLE AUDIT_DDL ( 
DDL_DATE date, 
OSUSER varchar2(255),
CURRENT_USER varchar2(255),
HOST varchar2(255), 
TERMINAL varchar2(255), 
IP_ADDRESS VARCHAR2(100), 
module varchar2(100),
owner varchar2(30), 
type varchar2(30), 
name varchar2(30), 
sysevent varchar2(30),
sql_txt varchar2(4000) ) 
tablespace tbs_audit ;

--- Trigger will be created at sys user, so that all statements will be captured in any schema in the database

create or replace trigger
sys.audit_ddl_trg after ddl on database
declare
sql_text ora_name_list_t;
stmt VARCHAR2(4000) := '';
n number;
begin
n:=ora_sql_txt(sql_text);
for i in 1..n
loop
stmt:=substr(stmt||sql_text(i),1,4000);
end loop;
insert into audit_ddl(
DDL_DATE,osuser,
current_user,host,
terminal,
ip_address,module,
owner,
type,name,sysevent,sql_txt)
values(
sysdate,
sys_context('USERENV','OS_USER') ,
sys_context('USERENV','CURRENT_USER') ,
sys_context('USERENV','HOST') ,
sys_context('USERENV','TERMINAL') ,
UTL_INADDR.get_host_name('USERENV'),
sys_context('USERENV','MODULE') ,
ora_dict_obj_owner,
ora_dict_obj_type,
ora_dict_obj_name,
ora_sysevent,
stmt
);
end;
/

-- Sql Query can be used to lookup the captured ddl in the audit_ddl table.
col type format a10
col name format a10
col host format a16
col IP_ADDRESS format a10
col terminal format a20
col owner format a15
col sql_txt format a20
col SYSEVENT format a10
col CURRENT_USER format a10
col osuser format a10
select * from AUDIT_DDL;