Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PLSQL Oracle触发器,按id对行中的金额求和_Sql_Oracle_Plsql_Database Trigger - Fatal编程技术网

PLSQL Oracle触发器,按id对行中的金额求和

PLSQL Oracle触发器,按id对行中的金额求和,sql,oracle,plsql,database-trigger,Sql,Oracle,Plsql,Database Trigger,我有这样的桌子: create or replace trigger trg_producers BEFORE INSERT OR DELETE OR UPDATE ON producers FOR EACH ROW declare pragma autonomous_transaction; producerShippedAmount number(10):=0; begin SELECT SUM(amount) INTO producerShippedAmount

我有这样的桌子:

create or replace trigger trg_producers 
BEFORE INSERT OR DELETE OR UPDATE
    ON producers
    FOR EACH ROW 
declare 
pragma autonomous_transaction;
producerShippedAmount number(10):=0;
begin

SELECT SUM(amount) INTO producerShippedAmount 
        FROM Shippings
        WHERE ProducernName = :NEW.Name;

:new.amount := producerShippedAmount;


end trg_producers;
发货表:

ProducernName| ... |Amount
A            |...  |1
B            |...  |2
A            |...  |5
C            |...  |3
C            |...  |5
ProducernName| ... |Amount
A            |...  |1
B            |...  |2
A            |...  |5
C            |...  |3
C            |...  |5
和另一张生产商表:

Name|...| Shipped Amount
A   |...|  NULL
B   |...|  NULL
C   |...|  NULL
Name|...| Amount
A   |...|  NULL
B   |...|  NULL
C   |...|  NULL
其思想是创建一个触发器,对每个生产商的Shippings表中的发货量求和,并在任何更改(更新、删除、插入)后在生产商表中进行更新 如果触发器工作,则Producers表将如下所示:

Name|...| Shipped Amount
A   |...|  6
B   |...|  2
C   |...|  8
我试图找到金额的总和,并将其保存在我声明的变量中,但我不知道我的思维方向是否正确,以及如何将总和插入表中的正确行

CREATE TRIGGER SumShippedTrigger
AFTER INSERT OR DELETE OR UPDATE
OF amount
ON SHIPPINGS
FOR EACH ROW 
DECLARE
        producerShippedAmount NUMBER(10);
        producer VARCHAR2(10);
BEGIN
        SELECT SUM(amount) INTO producerShippedAmount 
        FROM Shippings
        WHERE producer= :NEW.producer;


    producer:= :NEW.procuder;
    END;
/


如果有人能帮助我,我会很感激的!:)

为什么要为此使用触发器?数据是否太大,无法进行简单的汇总:

select producer, sum(amount)
from shippings
group by producer;
您可以很容易地为单个制作人查找此内容(使用
where
),并使用索引使其更高效

如果您使用触发器,我会说,通常情况下,方法是增量更改总和:

CREATE TRIGGER SumShippedTrigger
    AFTER INSERT OR DELETE OR UPDATE OF amount
    ON SHIPPINGS
    FOR EACH ROW 
BEGIN
    UPDATE producers
        SET amount = COALESCE(amount, 0) + COALESCE(:new.amount, 0) - COALESCE(:old.amount, 0)
        WHERE producer = COALESCE(:NEW.producer, :OLD.producer);
END;

虽然您的方法在逻辑上是正确的,但它所做的工作超出了必要的范围,可能会导致表触发器错误。

为了查看以下表:

发货表:

ProducernName| ... |Amount
A            |...  |1
B            |...  |2
A            |...  |5
C            |...  |3
C            |...  |5
ProducernName| ... |Amount
A            |...  |1
B            |...  |2
A            |...  |5
C            |...  |3
C            |...  |5
另一张表是生产者:

Name|...| Shipped Amount
A   |...|  NULL
B   |...|  NULL
C   |...|  NULL
Name|...| Amount
A   |...|  NULL
B   |...|  NULL
C   |...|  NULL
您可以在
producers
表中声明触发器,如下所示:

create or replace trigger trg_producers 
BEFORE INSERT OR DELETE OR UPDATE
    ON producers
    FOR EACH ROW 
declare 
pragma autonomous_transaction;
producerShippedAmount number(10):=0;
begin

SELECT SUM(amount) INTO producerShippedAmount 
        FROM Shippings
        WHERE ProducernName = :NEW.Name;

:new.amount := producerShippedAmount;


end trg_producers;

有必要提及的是,必须声明pragma autonomy_事务

需要对@Gordon代码稍作修改。触发器触发DELETE,然后:new。是空的。因此where子句也需要与它们结合起来。“WHERE producer=coalesce(:NEW.producer;:Old.producer)@Belayer…很好的捕获。谢谢。非常感谢您的回复!但是我尝试了您的方法,但Producers表中我的amount行没有任何更改(将所有值插入表中后仍然为null)@Ian…这似乎有点问题。如果名称匹配,那么值至少应该更改为
0
,而不是
NULL
。听起来好像没有调用触发器。或者,匹配条件没有产生实际的匹配。@Ian:您提交了更改吗?设计规则#2749:不存储摘要数据。您将在你职业生涯的剩余时间里,找出错误的原因。相反,在你需要的时候总结数据-然后它会是正确的,至少是暂时的。当我们对他们所拥有的表执行DML时触发。此触发器仅在生产者记录更改时更新生产者.AMOUNT。这显然不是OP的意图:他们想要更新SHIPPERS表更新时的PRODUCERS表。好的,这种方法是正确的,以便将PRODUCERS表更改为SHIPPERS表的更改,因此哪种方法适合您取决于您的业务,即使您可以在不使用触发器的情况下达到目标。我建议您可以在服务器端使用触发器进行处理。使用trigger不是合适的解决方案当你说“服务器端”是什么意思?数据库服务器可以被视为“服务器端”,那么你的建议是什么?