我遇到的问题是Java进程(我无法控制)是将行插入表中并导致溢出。我无法拦截查询,ORACLE引发的异常并不能提供信息。它只提到溢出,但没有提到它发生在哪一列。
我想知道哪个查询导致此溢出以及插入的值。
我尝试在表上创建一个触发器BEFORE INSERT,将行复制到另一个我可以稍后读取的临时表中,但是当溢出发生时看起来似乎没有运行触发器。
触发语法:
CREATE OR REPLACE TRIGGER OVERFLOW_TRIGGER
BEFORE INSERT
ON VICTIM_TABLE
FOR EACH ROW
BEGIN
insert into QUERIES_DUMP values (
:old.COL1, :old.COL2, :old.COL3,
:old.COL4, :old.COL5, :old.COL6,
:old.COL7, :old.COL8, :old.COL9,
:old.COL10, :old.COL11, :old.COL12
);
END;
/
表QUERIES_DUMP具有与失败表相同的结构,但NUMBER和VARCHAR2列被推到最大容量。我希望得到一个查询列表,然后找出哪些是违反规则的。
即使设置为在插入之前运行,是否期望触发器在溢出的情况下不运行?
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Prod
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for Solaris: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
EDIT1:
抛出的错误是:
Description: Error while query: INSERT INTO
...
ORA-01438: value larger than specified precision allowed for this column
我所知道的是,在任何地方都没有插入错误的类型。它很可能是其中一个数字字段的长度,但是它们很多并且插入过程需要一个多小时,所以我不能强行猜测列。
我已经考虑过备份表并使用更大的列创建一个新的victim_table,但是这个过程实际上插入了很多其他表以及复杂的数据模型中,并且DB有一些敏感的信息所以我不能通过移动来危害其一致性。
我尝试了一个INSTEAD OF触发器,但ORACLE似乎不接受INSTEAD OF表示插入。
我添加了JDBC层的日志记录,但是我得到的查询没有值,只有'?'
Description: Error while query: INSERT INTO VICTIM_TABLE ( . . . ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
答案 0 :(得分:1)
这取决于具体的错误(包括ORA-xxxxx错误号总是非常感谢)。
如果问题是Java应用程序试图插入无法转换为表的数据类型的值,那么在触发器运行之前可能会抛出该错误。数据类型验证必须在触发器执行之前进行。
想象一下,如果在触发器运行后发生数据类型验证会发生什么。如果Java应用程序为col1
传递了无效值,那么在触发器内部,:new.col1
将具有基础表中col1
所具有的数据类型,但会有无效值。因此,对该字段的任何引用都需要引发错误 - 您无法将无效值记录到您的表中。
您确定无法以某种方式拦截查询吗?例如,如果您将victim_table
重命名为victim_table_base
,则创建一个名为victim_table
的视图,其中包含更大的数据类型,然后在视图上定义instead of
触发器,以验证数据和将其插入表中,您可以识别哪些值无效。或者,由于您的Java应用程序使用JDBC(可能)与数据库交互,因此您应该能够在JDBC层启用日志记录以查看正在传递的参数值。