我在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等...)
答案 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。
除此之外,使用“三触发解决方案”解决变异表错误是可能的,虽然相当麻烦。
然而,正如您可能想象的那样,三个触发解决方案涉及相当数量的移动部件,因此不是特别明智。
你也可以使用快速刷新的物化视图来实现这种东西,但我不认为这是数据库快速版中的一个选项(虽然我可能错了)。