【问题标题】:Oracle validate range for overlapping valueOracle 验证重叠值的范围
【发布时间】:2016-10-29 09:55:17
【问题描述】:

我正在尝试验证 Oracle 表中的范围值。表名YEAR_RANG是这样的

ID  YEAR_FROM  YEAR_TO
1       1950    1980
2       2001    2009
3       2010    2015
4       2016    2020

这里我想做一个约束,两行的年份范围不能重叠。我正在尝试使用以下触发器来做到这一点,

CREATE OR REPLACE TRIGGER YEAR_RANG_VALID
BEFORE INSERT or UPDATE on YEAR_RANG
FOR EACH ROW
  DECLARE
    o_exst NUMBER;
  BEGIN
    select count(*) into o_exst
    FROM YEAR_RANG
    WHERE
      id != :new.id
      and GREATEST(YEAR_FROM,:new.YEAR_FROM) <= LEAST(YEAR_TO,:new.YEAR_TO)
      and ROWNUM = 1;
    IF o_exst = 1 THEN
      raise_application_error( -20202, 'Range overlap');
    END IF;
  END;

这适用于输入,但对于更新,它给出了这个错误

[42000][4091] ORA-04091: table DB.YEAR_RANG is mutating, trigger/function may not see it
ORA-06512: at "DB.YEAR_RANG_VALID", line 4
ORA-04088: error during execution of trigger 'DB.YEAR_RANG_VALID'

更改为“在 YEAR_RANG 上插入或更新之后”也无济于事。如何进行验证检查?我的触发器没问题还是有更好的方法?

还有一件事,我无法在应用程序级别检查这一点,因为这是从通用 CRUD 框架调用的,DB fail 是检测约束失败的唯一方法。

【问题讨论】:

  • 你不能创建一个触发器来获取你正在插入的同一个表中的值,至少不是 BEFORE 类型的。看看您是否可以通过 AFTER insert 或 update 获得它。不记得是否可能。
  • @TigerCoder 你试过语句级触发器吗? stackoverflow.com/questions/10167346/…
  • 由于该表显然只有少量行,@vercelli 对语句级触发器的建议非常合适:只需检查语句 no 重叠之后表中存在行。 (如果表格有数百万行,那么您就不想这样做了。)
  • @vercelli 语句级触发器就是答案。谢谢(你的)信息。如果您能给出您的评论作为答案,我会接受。

标签: database oracle validation oracle11g triggers


【解决方案1】:

删除FOR EACH ROW 使其成为语句级触发器。 row-level trigger vs statement-level trigger

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多