mysql触发到oracle触发器

时间:2010-11-17 23:00:43

标签: sql mysql database oracle triggers

我在mysql中写了一个触发器,检查一个人是否能够查看另一个库项目。我设置的结账限制是3.我需要将其转换为Oracle触发器,但是我遇到了很多问题。

这是我的MySQL代码:

DELIMITER //
DROP TRIGGER IF EXISTS library.CheckBorrowsTable//
CREATE TRIGGER CheckBorrowsTable
BEFORE INSERT ON library.Borrows
FOR EACH ROW
BEGIN
IF ((SELECT COUNT(*) FROM library.Borrows WHERE libraryID = new.libraryID) >= 3)THEN
SET new = NULL;
END IF;
END//
DELIMITER ;

这是我的Oracle代码:

IF((SELECT COUNT(libraryID) FROM Borrows WHERE libraryID = :NEW.libraryID) >= 3) THEN
:NEW = NULL;
END IF;

我的Oracle代码还有其他部分,但Oracle Express Edition添加了这些部分(Begin,End等...)

1 个答案:

答案 0 :(得分:3)

表A上的行级触发器(即library.borrows)无法查询表A.如果这样做,您将获得变异表异常(除非您可以保证只进行单行插入VALUES条款)。因此,这不会被认为是Oracle的良好开发实践。

实现此类要求的最合理方式不是通过触发器。相反,如果您的应用程序调用存储过程API,您将拥有一个存储过程(即CHECK_OUT),该存储过程首先查询表以确定个人已签出多少本书,并且仅当顾客在下面时才将该行插入BORROWS表中他或她的限制。

第二种方法是将签出的项目数存储在单独的表中。如果你有一个带有NUM_CHECKED_OUT列的PATRONS表,并且你的BORROWS表有一个PATRON_ID来指示谁借了这本书,你的触发器可以做类似的事情

CREATE OR REPLACE TRIGGER CheckBorrowsTable
  BEFORE INSERT ON library.borrows
  FOR EACH ROW
BEGIN
  UPDATE patrons p
     SET p.num_checked_out = p.num_checked_out + 1
   WHERE p.patron_id = :new.patron_id
END;

以及PATRONS表上的CHECK约束,以确保NUM_CHECKED_OUT永远不会超过3。

除此之外,使用“三触发解决方案”解决变异表错误是可能的,虽然相当麻烦。

  1. BEFORE INSERT语句级别 触发器清除一个集合 你已经在一个包中创建了。
  2. BEFORE INSERT行级别触发器 写主键(或ROWID) 被修改为行的行 集合。
  3. AFTER INSERT语句 level触发器从中读取数据 集合,查询表, 并确定是否有任何插入 违反了商业规则。如果 他们做了,抛出异常。
  4. 然而,正如您可能想象的那样,三个触发解决方案涉及相当数量的移动部件,因此不是特别明智。

    你也可以使用快速刷新的物化视图来实现这种东西,但我不认为这是数据库快速版中的一个选项(虽然我可能错了)。