【问题标题】:Capture ORACLE query causing overflow on table捕获导致表溢出的 ORACLE 查询
【发布时间】:2014-08-22 08:02:29
【问题描述】:

我遇到了一个问题,即 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

我所知道的是,在任何地方都没有插入错误的类型。这很可能是其中一个数字字段的长度,但它们数量众多,插入过程需要一个多小时,所以我无法强行猜测该列。

我考虑过备份表并创建一个具有更大列的新受害者表,但该过程实际上插入到许多其他表以及复杂数据模型中,并且数据库具有一些敏感信息,所以我不能移动东西会危及它的一致性。

我尝试了 INSTEAD OF 触发器,但 ORACLE 似乎不接受 INSTEAD OF 用于表上的插入。

我在 JDBC 层添加了日志记录,但我得到的查询没有值,只有“?”

Description: Error while query: INSERT INTO VICTIM_TABLE ( . . . ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)

【问题讨论】:

  • 您需要在autonomous transaction 中插入。它正在回滚。
  • 开启追踪,然后运行 ​​TKPROF。

标签: java sql oracle


【解决方案1】:

这取决于具体的错误(包括 ORA-xxxxx 错误号总是非常感谢)。

如果问题是 Java 应用程序试图插入一个无法转换为表数据类型的值,那么在触发器运行之前应该会抛出该错误。数据类型验证必须在触发器执行之前进行。

想象一下,如果数据类型验证发生在触发器运行之后会发生什么。如果 Java 应用程序为 col1 传递了一个无效值,那么在触发器内部,:new.col1 将具有基础表中 col1 的任何数据类型,但将具有无效值。因此,对该字段的任何引用都需要引发错误——您无法合理地将无效值记录到您的表中。

您确定不能以某种方式拦截查询吗?例如,如果您将victim_table 重命名为victim_table_base,创建了一个名为victim_table 的具有更大数据类型的视图,然后在验证数据并将其插入表中的视图上定义了instead of 触发器,您可以确定哪些值无效。或者,由于您的 Java 应用程序(可能)使用 JDBC 与数据库交互,您应该能够在 JDBC 层启用日志记录以查看正在传递的参数值。

【讨论】:

  • 非常感谢您的详细回复。你能再看一遍我的问题吗?我根据您提供的建议对其进行了更新。
  • @OdayMansour - 如果您想使用instead of 触发器方法,您需要重命名表、创建视图并在视图上定义触发器。您不能在表上定义 instead of 触发器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多