触发器用于查找不同表中的一个字段的总和,如果超过 oracle 中的某个值,则会出错

发布于 2024-11-04 06:17:13 字数 1319 浏览 0 评论 0原文

我有两个表

moduleprogress 其中包含字段:

studentid
模块代码
moduleyear

模块包含以下字段:

modulecode

当用户尝试在 moduleprogress 表中插入或更新数据时,我需要一个触发器来运行

触发器需要:

  1. 查看用户输入的学生 ID 并查看他们在 moduleyear“1”中学习的所有模块。
  2. 获取用户输入的模块代码并查看模块表并找到所有这些模块的学分字段的总和(每个模块值 10 或 20 学分)。
  3. 如果该值高于 120(年度信用额度),则需要出错;如果没有,则输入正常。

这有道理吗?这可能吗?


@a_horse_with_no_name

这看起来会起作用,但我只会使用数据库手动输入数据,因此需要在输入时出错。我试图获得与此类似的触发器来解决问题(触发器不起作用)并忘记“UOS_”位于一切之前。只是帮助我处理数据库和其他功能。

CREATE OR REPLACE TRIGGER  "UOS_TESTINGS"     
BEFORE UPDATE OR INSERT ON UOS_MODULE_PROGRESS    
REFERENCING NEW AS NEW OLD AS OLD    
DECLARE    
    MODULECREDITS INTEGER;    
BEGIN    
    SELECT    
            m.UOS_CREDITS,    
            mp.UOS_MODULE_YEAR,    
            SUM(m.UOS_CREDITS)    
    INTO    MODULECREDITS    
    FROM    UOS_MODULE_PROGRESS mp JOIN UOS_MODULES m    
    ON      m.UOS_MODULE_CODE = mp.UOS_MODULE_CODE    
    WHERE   mp.UOS_MODULE_YEAR = 1;    


    IF MODULECREDITS >= 120 THEN    
        RAISE_APPLICATION_ERROR(-20000, 'Students are only allowed to take upto 120 credits per year');    
    END IF;    
END;  

我收到错误消息:

8 23 PL/SQL: ORA-00947: 没有足够的值
4 1 PL/SQL:忽略 SQL 语句

I have two tables

moduleprogress which contains fields:

studentid
modulecode
moduleyear

modules which contains fields:

modulecode
credits

I need a trigger to run when the user is attempting to insert or update data in the moduleprogress table.

The trigger needs to:

  1. look at the studentid that the user has input and look at all modules that they have taken in moduleyear "1".
  2. take the modulecode the user input and look at the modules table and find the sum of the credits field for all these modules (each module is worth 10 or 20 credits).
  3. if the value is above 120 (yearly credit limit) then it needs to error; if not, input is ok.

Does this make sense? Is this possible?


@a_horse_with_no_name

This looks like it will work but I will only be using the database to input data manually so it needs to error on input. I'm trying to get a trigger similar to this to solve the problem(trigger doesn't work) and forget that "UOS_" is before everything. Just helps me with my database and other functions.

CREATE OR REPLACE TRIGGER  "UOS_TESTINGS"     
BEFORE UPDATE OR INSERT ON UOS_MODULE_PROGRESS    
REFERENCING NEW AS NEW OLD AS OLD    
DECLARE    
    MODULECREDITS INTEGER;    
BEGIN    
    SELECT    
            m.UOS_CREDITS,    
            mp.UOS_MODULE_YEAR,    
            SUM(m.UOS_CREDITS)    
    INTO    MODULECREDITS    
    FROM    UOS_MODULE_PROGRESS mp JOIN UOS_MODULES m    
    ON      m.UOS_MODULE_CODE = mp.UOS_MODULE_CODE    
    WHERE   mp.UOS_MODULE_YEAR = 1;    


    IF MODULECREDITS >= 120 THEN    
        RAISE_APPLICATION_ERROR(-20000, 'Students are only allowed to take upto 120 credits per year');    
    END IF;    
END;  

I get the error message :

8 23 PL/SQL: ORA-00947: not enough values

4 1 PL/SQL: SQL Statement ignored

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

微凉 2024-11-11 06:17:13

我不确定我是否理解您的描述,但就我的理解而言,这可以使用物化视图来解决,这可能会比触发器提供更好的事务行为:

CREATE MATERIALIZED VIEW LOG 
  ON moduleprogress WITH ROWID (modulecode, studentid, moduleyear) 
  INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG 
  ON modules with rowid (modulecode, credits) 
  INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW mv_module_credits
REFRESH FAST ON COMMIT WITH ROWID
AS
SELECT pr.studentid,
       SUM(m.credits) AS total_credits
FROM moduleprogress pr 
  JOIN modules m ON pr.modulecode = m.modulecode
WHERE pr.moduleyear = 1
GROUP BY pr.studentid;

ALTER TABLE mv_module_credits
   ADD CONSTRAINT check_total_credits CHECK (total_credits <= 120)

但是:取决于然而,这可能比纯粹基于触发器的解决方案慢。

此解决方案的唯一缺点是,错误将在提交时抛出,而不是在插入发生时抛出(因为 MV 仅在提交时刷新,然后评估检查约束)

I'm not sure I understand your description, but the way I understand it, this can be solved using a materialized view, which might give better transactional behaviour than the trigger:

CREATE MATERIALIZED VIEW LOG 
  ON moduleprogress WITH ROWID (modulecode, studentid, moduleyear) 
  INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW LOG 
  ON modules with rowid (modulecode, credits) 
  INCLUDING NEW VALUES;

CREATE MATERIALIZED VIEW mv_module_credits
REFRESH FAST ON COMMIT WITH ROWID
AS
SELECT pr.studentid,
       SUM(m.credits) AS total_credits
FROM moduleprogress pr 
  JOIN modules m ON pr.modulecode = m.modulecode
WHERE pr.moduleyear = 1
GROUP BY pr.studentid;

ALTER TABLE mv_module_credits
   ADD CONSTRAINT check_total_credits CHECK (total_credits <= 120)

But: depending on the size of the table this might however be slower than a pure trigger based solution.

The only drawback of this solution is, that the error will be thrown at commit time, not when the insert happens (because the MV is only refreshed on commit, and the check constraint is evaluated then)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文