我是Oracle的初学者。我正在尝试创建一个INSTEAD OF触发器来强制执行一个规则,即教师不应该在一个月内工作超过60小时
这是我到目前为止所拥有的
CREATE TRIGGER limit_hour
INSTEAD OF INSERT ON SESSIONHOURS
DECLARE
totalHours NUMBER := 60;
monthOnly DATE;
totalSession NUMBER;
FOR EACH ROW
BEGIN
INSERT INTO SESSIONHOURS(SESSIONDATEKEY, TUTORKEY, TOTALSESSION)
SELECT EXTRACT (MONTH FROM DATE S.SESSIONDATEKEY), S.TOTALSESSION
INTO monthOnly, totalSession
FROM SESSIONHOURS S
END;
错误“不适当的INTO”不断弹出。此外,我需要为提取的月份分配每个会话的总和(每个30分钟),然后将其与“totalHour”进行比较。如何为日期值分配时间值?任何建议将不胜感激
答案 0 :(得分:0)
您的INSERT语句编写不正确。它应该是:
INSERT INTO SESSIONHOURS(SESSIONDATEKEY, TOTALSESSION)
SELECT EXTRACT (MONTH FROM DATE S.SESSIONDATEKEY), S.TOTALSESSION
FROM SESSIONHOURS S
这不会解决你的总时数"问题,但它会处理您报告的错误。
祝你好运。
答案 1 :(得分:0)
在我看来,BEFORE INSERT触发器更合适,而不是使用INSTEAD OF触发器。 INSTEAD OF触发器通常用于将不可插入视图上的INSERT映射到INSERT到所需的表中。另一方面,BEFORE INSERT触发器在每行插入表之前触发,允许检查行中的值的一致性等。这样的触发器可以如下使用:
(arrays) => "?" + arrays.filter(({length}) => length > 1).map(([tax, ...cats]) => `${tax}=${cats.join(",")}`).join("&")
在处理INSESS进入SESSIONHOURS之前将触发此触发器。它查询数据库以确定其密钥位于INSERT语句(CREATE TRIGGER SESSIONHOURS_BI
BEFORE INSERT INTO SESSIONHOURS
FOR EACH ROW
DECLARE
nTotal_tutor_hours NUMBER;
BEGIN
SELECT SUM(HOURS)
INTO nTotal_tutor_hours
FROM SESSIONHOURS s
WHERE s.TUTORKEY = :new.TUTORKEY;
IF nTotal_tutor_hours + :new.HOURS > 60 THEN
RAISE_APPLICATION_ERROR(-20001, 'Addition of ' || :new.HOURS ||
' for tutor ' || :new.TUTORKEY ||
' exceeds monthly limit of 60');
END IF;
END SESSIONHOURS_BI;
)中的教师的总工作小时数。如果工作总时数加上新记录中的小时数超过60,则会引发异常,从而导致INSERT中止。否则触发器正常返回,INSERT继续。
然而 - 即使这样也行不通。问题是触发器是在SESSIONHOURS表上定义的,而在触发器内部,SESSIONHOURS表上有一个SELECT。这将导致数据库抛出可怕的:new.TUTORKEY
异常,并附有解释性文本ORA-04091
。有几种方法可以解决这个问题,其中最好的方法是遵循一个简单的规则:
***永远不要*在触发器中实施商业逻辑!!!!
诸如“导师可能不会超过60小时工作”的规则是一项商业规则。这应该在您的应用程序逻辑中实现,而不是在触发器中实现。在数据库中创建过程或函数以执行INSERT INTO SESSIONHOURS和任何所需的验证逻辑,并在每次需要将数据插入SESSIONHOURS时调用该过程。不要尝试将验证逻辑置于触发器中 - 您会发现它非常困难,并且会导致永无止境的调试会话as noted here。
祝你好运。