1

Temat: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

2

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Dobrze rozumiem, że po każdym INSERT do tabeli sprzedaż powinien być update do tabeli sprzedawca, który automatycznie aktualizuje wielkość sprzedaży? O to chodzi?

3

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Dokladnie, dla kazdego sprzedawcy automatycznie powinien dopisac obrot.

4

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

DROP TABLE IF EXISTS sprzedaz;
DROP TYPE IF EXISTS sposob_zaplaty;
DROP TABLE IF EXISTS sprzedawca;
DROP FUNCTION IF EXISTS aktualizuj_obrot_sprzedawcy();

CREATE TABLE sprzedawca
(
    nr_sprzedawcy smallint PRIMARY KEY,
    imie text,
    nazwisko text NOT NULL,
    obrot_sprzedawcy numeric(11, 2) DEFAULT 0 NOT NULL
);

CREATE TYPE sposob_zaplaty AS ENUM ('Gotowka', 'Karta', 'Przelew', 'Raty');

CREATE TABLE sprzedaz
(
    pesel_klienta char(11), -- REFERENCES klient(pesel)
    nr_podwozia varchar(17), -- REFERENCES samochod(nr_podwozia)
    nr_sprzedawcy smallint REFERENCES sprzedawca(nr_sprzedawcy),
    sposob_zaplaty sposob_zaplaty,
    data_sprzedazy date,
    cena_finalna numeric(9,2) NOT NULL
);

Ostatnio edytowany przez gszpetkowski (2011-06-02 05:38:45)

5

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Bardzo dziekuje, o to wlasnie mi chodzilo. Wszystko dziala poprawnie. A jesli bym chcial przerobic go tak,aby nie byl on typu " and forget" co trzeba zmienic /dodac?

Pozdr.Patryk

6

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Gdyby to było konieczne, to wystarczy dodać kolejne wyzwalacze na UPDATE i DELETE analogicznie tak jak przy INSERT. Przykładowo jeżeli UPDATE miałby spowodować zmianę cena_finalna dla jakiejś sprzedaży, to w funkcji obsługi trigger'a wystarczy obliczyć różnicę między starą i nową cena_filnalna i zaaktulizować obrot_sprzedawcy.

7

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Cos takiego dla UPDATE?

"


CREATE FUNCTION aktualizuj_obrot_sprzedawcy_update() RETURNS TRIGGER AS $$
BEGIN
    UPDATE sprzedawca
    SET obrot_sprzedawcy = obrot_sprzedawcy + (cena_finalna - NEW.cena_finalna)
    WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER sprzedaz_insert
    AFTER UPDATE ON sprzedaz
    FOR EACH ROW
    EXECUTE PROCEDURE aktualizuj_obrot_sprzedawcy_update();

Ostatnio edytowany przez sali128 (2011-06-02 16:28:23)

8

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

CREATE FUNCTION aktualizuj_obrot_sprzedawcy_update() RETURNS TRIGGER AS $$
BEGIN
    UPDATE sprzedawca
    SET obrot_sprzedawcy = obrot_sprzedawcy + (NEW.cena_finalna - OLD.cena_finalna )
    WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;

    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER sprzedaz_update
    AFTER UPDATE ON sprzedaz
    FOR EACH ROW
    EXECUTE PROCEDURE aktualizuj_obrot_sprzedawcy_update();

9

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Dziala swietnie. Dziekuje... A czy jest mozliwosc zapisania jednego Triggera dla wszystkich funkcji UPDATE,INSTERT DELETE zamiast 3 osobnych? Chodzi mi o swoiste laczenie ich.

10

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

CREATE TRIGGER sprzedaz_update
    AFTER UPDATE OR INSERT  OR DELETE ON sprzedaż

11

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Witam,

Poczytalem to co napisaliscie i przeanalizowalem wczesniejsze Triggery @gszpetkowski i doszedlem do czegos takiego-jednak nie dziala.

CREATE FUNCTION obrot_sprzedawcy() RETURNS TRIGGER AS $obrot_sprzedawcy$
    BEGIN
   
    IF (TG_OP = 'DELETE') THEN
         
         ???
         
       
        ELSIF (TG_OP = 'UPDATE') THEN
   
    SET obrot_sprzedawcy = obrot_sprzedawcy + (NEW.cena_finalna - OLD.cena_finalna )
    WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;
    RETURN NEW;
   
        ELSIF (TG_OP = 'INSERT') THEN
   
    SET obrot_sprzedawcy = obrot_sprzedawcy + NEW.cena_finalna
    WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;
        RETURN NEW;
        END IF;
    END;

$obrot_sprzedawcy$ LANGUAGE plpgsql;

CREATE TRIGGER obrot_sprzedawcy
AFTER INSERT OR UPDATE OR DELETE ON sprzedawca
    FOR EACH ROW EXECUTE PROCEDURE obrot_sprzedawcy() ;


1)Nie wiem co wpisac w DELETE?
2)Prosze przeanalizowac ,bo nie wiem czy to na pewno jest dobrze.


Dziekuje i Pozdrawiam,
Patryk

Ostatnio edytowany przez sali128 (2011-06-06 14:07:54)

12

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

13

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Skladnia wydaje mi sie byc ok, a ma ktos pomysl na warunek DELETE?

14

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

"A może (chociaż) Harry Potter?" wink

-- DROP FUNCTION IF EXISTS obrot_sprzedawcy();

CREATE FUNCTION obrot_sprzedawcy() RETURNS TRIGGER AS $$
DECLARE
    delta numeric(9,2);
BEGIN
    IF (TG_OP = 'INSERT') THEN
        UPDATE sprzedawca
        SET obrot_sprzedawcy = obrot_sprzedawcy + NEW.cena_finalna
        WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;
        RAISE NOTICE 'Nowa sprzedaż, zwiększony obrót sprzedawcy % o % zł.',
            NEW.nr_sprzedawcy, NEW.cena_finalna;
        RETURN NEW;

    ELSIF (TG_OP = 'UPDATE') THEN
        delta := NEW.cena_finalna - OLD.cena_finalna;
        UPDATE sprzedawca
        SET obrot_sprzedawcy = obrot_sprzedawcy + delta
        WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;
        RAISE WARNING 'Korekta sprzedaży, obrót sprzedawcy % różnica % zł.',
            NEW.nr_sprzedawcy, delta;
        RETURN NEW;

    ELSE
        UPDATE sprzedawca
        SET obrot_sprzedawcy = obrot_sprzedawcy - OLD.cena_finalna
        WHERE nr_sprzedawcy = OLD.nr_sprzedawcy;
        RAISE WARNING 'Anulowanie sprzedaży, obrót sprzedawcy % zmniejszony o % zł,',
            OLD.nr_sprzedawcy, OLD.cena_finalna;
        RETURN NEW;
    
    END IF;    
END;
$$ LANGUAGE plpgsql;

Samo CREATE TRIGGER już podał rski.

Przykład:

grzegorz=> \t
Showing only tuples.
grzegorz=> INSERT INTO sprzedaz VALUES ('78090726444', 'RE93032MFSDI203VE', 631, 'Karta', '2011-06-06', 355.50);
NOTICE:  Nowa sprzedaż, zwiększony obrót sprzedawcy 631 o 355.50 zł.
INSERT 0 1
grzegorz=> SELECT obrot_sprzedawcy FROM sprzedawca WHERE nr_sprzedawcy = 631;
         20255.50

grzegorz=> UPDATE sprzedaz SET cena_finalna = 200 WHERE pesel_klienta ~~ '78090726444' AND nr_podwozia ~~ 'RE93032MFSDI203VE';
WARNING:  Korekta sprzedaży, obrót sprzedawcy 631 różnica -155.50 zł.
UPDATE 1
grzegorz=> SELECT obrot_sprzedawcy FROM sprzedawca WHERE nr_sprzedawcy = 631;
         20100.00

grzegorz=> DELETE FROM sprzedaz WHERE pesel_klienta ~~ '78090726444' AND nr_podwozia ~~ 'RE93032MFSDI203VE';
WARNING:  Anulowanie sprzedaży, obrót sprzedawcy 631 zmniejszony o 200.00 zł,
DELETE 1
grzegorz=> SELECT obrot_sprzedawcy FROM sprzedawca WHERE nr_sprzedawcy = 631;
         19900.00

Właśnie dlatego narzekałem o ten klucz podstawowy w sprzedaz, żeby nie robić potem konstrukcji typu powyższego.

Te dodatkowe informacje (poziomy NOTICE i WARNING) służą dla czytelności, ale mogą być także umieszczane w logu pracy serwera (jeśli jest to wymagane, np. tylko poziom WARNING).

Ostatnio edytowany przez gszpetkowski (2011-06-06 18:09:47)

15

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Witam,

Dziekuje za odpowiedz. Robie wszystko tak jak nalezy,mam kod:


        CREATE FUNCTION obrot_sprzedawcy() RETURNS TRIGGER AS $$
DECLARE
    delta numeric(9,2);
BEGIN
    IF (TG_OP = 'INSERT') THEN
        UPDATE sprzedawca
        SET obrot_sprzedawcy = obrot_sprzedawcy + NEW.cena_finalna
        WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;
        RAISE NOTICE 'Nowa sprzedaż, zwiększony obrót sprzedawcy % o % zł.',
            NEW.nr_sprzedawcy, NEW.cena_finalna;
        RETURN NEW;

    ELSIF (TG_OP = 'UPDATE') THEN
        delta := NEW.cena_finalna - OLD.cena_finalna;
        UPDATE sprzedawca
        SET obrot_sprzedawcy = obrot_sprzedawcy + delta
        WHERE nr_sprzedawcy = NEW.nr_sprzedawcy;
        RAISE WARNING 'Korekta sprzedaży, obrót sprzedawcy % różnica % zł.',
            NEW.nr_sprzedawcy, delta;
        RETURN NEW;

    ELSE
        UPDATE sprzedawca
        SET obrot_sprzedawcy = obrot_sprzedawcy - OLD.cena_finalna
        WHERE nr_sprzedawcy = OLD.nr_sprzedawcy;
        RAISE WARNING 'Anulowanie sprzedaży, obrót sprzedawcy % zmniejszony o % zł,',
            OLD.nr_sprzedawcy, OLD.cena_finalna;
        RETURN NEW;
   
    END IF;   
END;
$$ LANGUAGE plpgsql;

         
  CREATE TRIGGER sprzedaz_update
    AFTER UPDATE ON sprzedaz
    FOR EACH ROW
    EXECUTE PROCEDURE obrot_sprzedawcy();
   
   
   
----WYKORZYSTANIE----
--UPDATE:

s8201=> UPDATE sprzedaz SET cena_finalna=10000 WHERE nr_podwozia LIKE 'FR873432846523H98';
OSTRZEŻENIE:  Korekta sprzedaży, obrót sprzedawcy 631 różnica 100.00 zł.
UPDATE 1

--INSERT:   
   
     
     INSERT INTO klient(pesel, nazwisko, imie, kod_pocztowy, miasto, ulica_dom)
   values('78090726444','Banicki','Marian','80-312','Szymbark','Dolna 12');
     INSERT INTO sprzedaz VALUES ('78090726444', 'GD0920490329FD093', 631, 'Karta', '2009-04-20', 48440);
     
     
     
--DELETE:


    DELETE FROM sprzedaz WHERE pesel_klienta ~~ '78090726444' AND nr_podwozia ~~ 'GD0920490329FD093';





Nie dziala w tej funkcji opcja INSERT i DELETE . UPDATE jest ok-wyswietla komunikat.
W insercie i delete nie wyswietla komunikatow i nie zlicza tych nowych wartosci. W insercie najpierw wpisuje nowego klienta
i nastepnie robie insert do tabeli sprzedaz jednak nic sie nie dzieje,tak samo przy delete. Cos robie zle? Moze zle trigger zapisalem?

Pozdr.

16

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

CREATE TRIGGER sprzedaz_update
    AFTER UPDATE ON sprzedaz
    FOR EACH ROW
    EXECUTE PROCEDURE obrot_sprzedawcy();

17

Odp: [POMOC] Przygotowanie TRIGGERA do projektu. Pilne!

Faktycznie,przeoczylem....

Wszystko smiga, dziekuje bardzo za cale Wasze zainteresowanie.


Dziekuje i Pozdrawiam.

Patryk