0

我的表中有很多触发器,但其中一个的行为并不完全符合我的要求。

这个计算产品和价格并返回订单总价 - 工作正常:

CREATE OR REPLACE FUNCTION ustawwartosczamowienia() RETURNS TRIGGER AS $$

DECLARE

przed NUMERIC;
po NUMERIC;
ile NUMERIC;


BEGIN
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN

SELECT cena*zamowienieilosc INTO ile FROM zamowienie_zawiera INNER JOIN zamowienie on zamowienie.id=zamowienie_idzamowienie inner join egzemplarz on zamowienie_zawiera.egzemplarz_idegzemplarz=egzemplarz.id inner join produkt on egzemplarz.produkt_idprodukt = produkt.id WHERE zamowienieilosc = new.zamowienieilosc;

SELECT wartosczamowienia INTO przed FROM zamowienie WHERE zamowienie.id = new.zamowienie_idzamowienie;


po := przed+ile;
UPDATE zamowienie SET wartosczamowienia=po WHERE zamowienie.id = new.zamowienie_idzamowienie;

ELSE
RAISE NOTICE 'Nie ma czegoś takiego';

END IF;

RETURN NEW;

END
$$
LANGUAGE 'plpgsql';


CREATE TRIGGER zamowieniewartosc
AFTER INSERT OR UPDATE
ON zamowienie_zawiera
FOR EACH ROW
EXECUTE PROCEDURE ustawwartosczamowienia();

然后我看到有人以 fe 1024 的价格购买了商品。所以我想把这笔钱添加到这个人的个人账户中,以便以后为他们的忠实客户提供特别优惠。我写了类似的触发器:

CREATE OR REPLACE FUNCTION kontododaj() RETURNS TRIGGER AS $$

DECLARE

przed NUMERIC;
po NUMERIC;
ile NUMERIC;

klient_idklient RECORD;


BEGIN
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN

SELECT sumazamowien INTO przed FROM klient WHERE klient.id = new.klient_idklient; 

SELECT wartosczamowienia INTO ile FROM zamowienie WHERE wartosczamowienia =  new.wartosczamowienia; 

po := przed + ile;

UPDATE klient SET sumazamowien=po WHERE klient.id = new.klient_idklient;

ELSE
RAISE NOTICE 'Nie ma czegoś takiego';

END IF;
RETURN NEW;

END
$$
LANGUAGE 'plpgsql';


CREATE TRIGGER kontoplus
AFTER INSERT OR UPDATE
ON zamowienie
FOR EACH ROW
EXECUTE PROCEDURE kontododaj();

然后我查看某人的帐户,他们有 2048 而不是 1024。我的触发器添加了两次钱。我应该改变什么?

4

2 回答 2

1

在不了解数据库结构的情况下很难找到原因,即。表的 DDL 和其他可能起作用的触发器的代码。

你写了“我的表中有很多触发器”,我怀疑它们之间存在一些连锁反应。如果是这种情况,我建议使用非触发过程来实现类似的逻辑。

顺便说一句,函数 kontododaj() 中可能存在逻辑错误。但在指出特定位置之前,让我简化一下代码。从 kontododaj() 正文:

IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN

    SELECT  sumazamowien
    INTO    przed
    FROM    klient
    WHERE   klient.id = new.klient_idklient; 

    SELECT  wartosczamowienia
    INTO    ile
    FROM    zamowienie
    WHERE   wartosczamowienia = new.wartosczamowienia; 

    po := przed + ile;

    UPDATE  klient
    SET     sumazamowien = po
    WHERE   klient.id = new.klient_idklient;

ELSE
    ...

上面的代码片段(在逻辑上)等效于:

IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN

    UPDATE  klient
    SET     sumazamowien = sumazamowien + new.wartosczamowienia
    WHERE   klient.id = new.klient_idklient;

ELSE
    ...

现在,我怀疑这段代码应该在更新后执行。考虑将值为 1024 的字段“wartosczamowienia”(订单的价值)设置为相同的值 1024 的情况。这将导致将 1024 添加到“sumazamowien”(订单的总价值),这是错误的。也许你应该尝试这种方式:

IF      TG_OP = 'INSERT'
THEN

    UPDATE  klient
    SET     sumazamowien = sumazamowien + new.wartosczamowienia
    WHERE   klient.id = new.klient_idklient;

ELSIF   TG_OP = 'UPDATE'
    AND new.wartosczamowienia <> old.wartosczamowienia
THEN

    UPDATE  klient
    SET     sumazamowien = sumazamowien + ( new.wartosczamowienia - old.wartosczamowienia )
    WHERE   klient.id = new.klient_idklient;

ELSE
    ...
于 2013-06-16T09:57:36.333 回答
1

一个非常可能的原因是您在一个表 zamowienie 上创建了两个触发器。PostgresSQL 中可以将多个触发器分配给一个表。这与我之前使用的其他数据库不同。我刚刚遇到这个问题并解决了。

By: SELECT * FROM pg_trigger; 您可以看到分配给您的表的触发器。删除不必要的触发器,就可以了。

于 2017-09-30T15:55:29.323 回答