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

Sql 一个触发器,用于查找不同表中一个字段的和,如果超过oracle中的某个值,则会出错,sql,oracle,validation,triggers,sum,Sql,Oracle,Validation,Triggers,Sum,我有两张桌子 moduleprogress包含以下字段: 学生 模块代码 模数式 包含以下字段的模块: 模块代码 学分 当用户试图在moduleprogress表中插入或更新数据时,我需要运行一个触发器 触发器需要: 查看用户输入的学生ID,并查看他们在moduleyear 1中学习的所有模块。 将模块编码为用户输入,并查看模块表,找到所有这些模块的学分字段总和。每个模块值10或20学分。 如果该值高于120年信用额度,则需要出错;如果没有,则输入正常。 这有意义吗?这可能吗 @没有名字的马 这

我有两张桌子

moduleprogress包含以下字段:

学生 模块代码 模数式

包含以下字段的模块:

模块代码 学分

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

触发器需要:

查看用户输入的学生ID,并查看他们在moduleyear 1中学习的所有模块。 将模块编码为用户输入,并查看模块表,找到所有这些模块的学分字段总和。每个模块值10或20学分。 如果该值高于120年信用额度,则需要出错;如果没有,则输入正常。 这有意义吗?这可能吗

@没有名字的马

这看起来会起作用,但我只会使用数据库手动输入数据,所以它需要在输入时出错。我正试图得到一个类似的触发器来解决这个问题触发器不起作用,忘记了UOS_uuu比一切都重要。只是帮助我处理数据库和其他功能

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语句被忽略

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

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仅在提交时刷新,然后计算检查约束

您可能会在此处运行一个突变触发器问题。另外,插入多行的独立并发事务又如何呢。这种设计有一种难闻的味道。你需要更精确地知道触发器不工作到底意味着什么。顺便问一下:UOS\U模块的数据类型是什么?如果是数值列,则不应对值1使用单引号。@JMoorhouse:如果仅插入单行,则可以在自动提交模式下执行此操作,然后立即得到错误。仅插入单行。如何使用自动提交模式?@JMoorhouse:这取决于您的编程环境。在Java/JDBC中,只需在底层连接上调用setAutoCommittrue。