アイテムが変更されるたびに親注文値を自動的に更新するトリガー関数を作成しようとしています。
これは私が作成したものです:
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();
これを実行しようとすると、次のエラーが発生します。
missing FROM-clause for table "old"
トリガーで元のテーブルへの参照を作成してみました。
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();
しかし、それはエラーsyntax error at or near "REFERENCING"
を与えるだけです。
元のorder_id
テーブルからorder_items
を取得するにはどうすればよいですか?
まず、_order_items
_テーブルにトリガーを作成するには、update_totals()
は トリガー関数でなければなりません which _RETURNS TRIGGER
_(boldは私のものです)。
データ変更トリガーは、引数なしの関数として宣言され、戻りタイプのトリガーです。 CREATE TRIGGERで指定された引数を受け取ることを想定している場合でも、関数は引数なしで宣言する必要があることに注意してください。
そうでない場合は、エラー_ERROR: function func_order_items must return type trigger
_が発生します。
2番目に、トリガーで_AFTER INSERT
_を使用する場合、OLD
を使用できないことに注意してください。そうでない場合は、エラー_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);
_