it-swarm.com.de

Zugriff auf den Tabellenwert OLD / NEW in einer Triggerfunktion in einfachem SQL

Ich versuche, eine Triggerfunktion zu erstellen, um die Werte der übergeordneten Bestellung automatisch zu aktualisieren, wenn sich eines der Elemente ändert.

Folgendes habe ich erstellt:

CREATE OR REPLACE FUNCTION update_totals() RETURNS void AS $$
    UPDATE orders SET
       total_fees = (SELECT SUM(fees) FROM order_items WHERE order_id = OLD.order_id),
       total_profit = (CASE WHEN total_cost IS NOT NULL THEN total - total_tax - total_cost - (SELECT SUM(fees) FROM order_items WHERE order_id = OLD.order_id) ELSE NULL END)
    WHERE id = OLD.order_id;
$$
LANGUAGE SQL;

CREATE TRIGGER update_totals AFTER INSERT 
OR UPDATE OF fees
ON order_items INITIALLY DEFERRED
FOR EACH ROW
WHEN ( OLD.* IS DISTINCT FROM NEW.* ) EXECUTE PROCEDURE update_totals();

Wenn ich versuche, dies auszuführen, wird folgende Fehlermeldung angezeigt:

missing FROM-clause for table "old"

Ich habe versucht, einen Verweis auf die ursprüngliche Tabelle im Trigger zu erstellen:

CREATE TRIGGER update_totals AFTER INSERT 
OR UPDATE OF fees
ON order_items
REFERENCING OLD ROW AS old_order
DEFERRABLE INITIALLY DEFERRED
FOR EACH ROW
WHEN ( OLD.* IS DISTINCT FROM NEW.* ) EXECUTE PROCEDURE update_totals();

Aber das gibt nur den Fehler syntax error at or near "REFERENCING".

Wie bekomme ich die order_id vom Original order_items Tabelle?

5
eComEvo

Erstens , um einen Trigger für die Tabelle order_items Zu erstellen, muss update_totals() eine Triggerfunktion) sein welches RETURNS TRIGGER ( fett mir gehört).

Ein Datenänderungsauslöser wird als eine Funktion ohne Argumente und mit einem Rückgabetyp des Auslösers deklariert. Beachten Sie, dass die Funktion mit keinen Argumenten deklariert werden muss, auch wenn erwartet wird, dass einige in CREATE TRIGGER angegebene Argumente empfangen werden

Wenn nicht, verursacht es einen Fehler ERROR: function func_order_items must return type trigger.

Zweitens , bitte denken Sie daran, dass Sie OLD nicht haben können, wenn AFTER INSERT Am Trigger ist. Wenn nicht, wird ein Fehler ausgelöst ERROR: record "old" is not assigned yet.

Zum Schluss sehen Sie sich bitte das folgende Beispiel an:

CREATE TABLE IF NOT EXISTS orders(ID INT NOT NULL PRIMARY KEY, X INT);
CREATE TABLE IF NOT EXISTS order_items (ID INT NOT NULL PRIMARY KEY, ORDER_ID INT, Y INT); 

INSERT INTO orders VALUES(1, 0);
INSERT INTO order_items VALUES(10, 1, 20);
INSERT INTO order_items VALUES(11, 1, 30);

CREATE OR REPLACE FUNCTION func_order_items() RETURNS trigger AS 
$$
BEGIN
  IF (TG_OP = 'UPDATE') THEN
    UPDATE orders
    SET X = (SELECT SUM(Y) FROM order_items WHERE order_id = OLD.order_id)
    WHERE ID = OLD.order_id;
  ELSIF (TG_OP = 'INSERT') THEN
    UPDATE orders
    SET X = (SELECT SUM(Y) FROM order_items WHERE order_id = NEW.order_id)
    WHERE ID = NEW.order_id;
  END IF;
  RETURN NULL;
END
$$
LANGUAGE PLPGSQL;

CREATE TRIGGER trigger_order_items 
AFTER INSERT OR UPDATE 
ON order_items 
FOR EACH ROW EXECUTE PROCEDURE func_order_items();

UPDATE order_items SET Y = 200 WHERE ID = 10;
INSERT INTO order_items VALUES (12, 1, 200);
5
Luan Huynh