J'essaie de créer une fonction de déclenchement pour mettre à jour automatiquement les valeurs de la commande parent à chaque fois que l'un de ses éléments change.
Voici ce que j'ai créé:
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();
Lorsque j'essaie d'exécuter cela, j'obtiens cette erreur:
missing FROM-clause for table "old"
J'ai essayé de créer une référence à la table d'origine dans le déclencheur:
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();
Mais cela donne juste l'erreur syntax error at or near "REFERENCING"
.
Comment obtenir le order_id
de l'original order_items
table?
Tout d'abord , pour créer un déclencheur sur la table order_items
, La update_totals()
doit être un déclencheur fonction qui RETURNS TRIGGER
( gras est le mien).
Un déclencheur de changement de données est déclaré comme une fonction sans arguments et un type de déclencheur de retour . Notez que la fonction doit être déclarée avec aucun argument même si elle s'attend à recevoir certains arguments spécifiés dans CREATE TRIGGER
Sinon, cela provoque une erreur ERROR: function func_order_items must return type trigger
.
Deuxièmement , n'oubliez pas que vous ne pouvez pas avoir OLD
lorsque AFTER INSERT
Sur le déclencheur. Sinon, il déclenche une erreur ERROR: record "old" is not assigned yet
.
Enfin , veuillez consulter l'exemple ci-dessous:
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);