eCo*_*Evo 7 postgresql functions postgresql-9.6
我正在尝试构建一个触发器函数,以便在任何项目发生更改时自动更新父订单值。
这是我创建的:
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();
Run Code Online (Sandbox Code Playgroud)
当我尝试运行它时,出现此错误:
missing FROM-clause for table "old"
Run Code Online (Sandbox Code Playgroud)
我尝试在触发器中创建对原始表的引用:
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();
Run Code Online (Sandbox Code Playgroud)
但这只是给出了错误syntax error at or near "REFERENCING"
。
如何order_id
从原始order_items
表中获取?
首先,在其上创建一个触发器order_items
表中,update_totals()
必须是一个触发功能,其RETURNS TRIGGER
(粗体是矿)。
数据更改触发器被声明为没有参数且返回类型为 trigger的函数。请注意,即使函数希望接收 CREATE TRIGGER 中指定的某些参数,也必须声明该函数 不带参数
如果不是,它会导致错误ERROR: function func_order_items must return type trigger
。
其次,请记住,你不能OLD
当AFTER INSERT
上了扳机。如果不是,它会引发错误ERROR: record "old" is not assigned yet
。
最后,请看下面的例子:
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);
Run Code Online (Sandbox Code Playgroud)