Reputation: 13
When i try execute this script, i get an error: ERROR: relation "old" does not exist. Script:
update organization
set row_status = 30;
I found some question like this, but their dont help me. My trigger:
Create OR REPLACE function PMigrateDataToHistory()
returns trigger as $PMigrateDataToHistory$
begin
insert into organization_history
select
*
from
OLD;
delete
from
organization as org USING
OLD as o
where
o.id = org.id and
o.version = org.version;
insert into organization
select
n.id,
n.created_at,
n.updated_at,
n.row_status,
n.version + 1,
n.resource
from
NEW as n;
end;
$PMigrateDataToHistory$ LANGUAGE plpgsql;
CREATE TRIGGER TRMigrateDataToHistory AFTER update or delete ON organization
FOR EACH ROW EXECUTE PROCEDURE PMigrateDataToHistory();
Upvotes: 0
Views: 2089
Reputation: 1
@Laurenz Albe is right, about using "DELETE" you have to use "BEFORE" not "AFTER" here are my examples(using postgresql):
create table if not exists v08_orders (
order_id serial primary key,
order_date DATE,
customer_name varchar(50));
create table if not exists v08_order_logs(
log_id serial primary key,
order_id INT,
log_date TIMESTAMP default CURRENT_TIMESTAMP,
log_text TEXT,
FOREIGN KEY (order_id) REFERENCES v08_orders (order_id) on delete set null);
create or replace function func_delete_order() returns trigger as $$ begin insert into v08_order_logs(order_id, log_text) values(OLD.order_id, 'an order is deleted ar: ' || CURRENT_TIMESTAMP); return OLD; end; $$ language plpgsql;
CREATE or replace TRIGGER order_delete_trigger
before DELETE ON v08_orders
FOR EACH ROW
execute function func_delete_order();
so every time you delete an item from the order, before deleting actually happens, an action of adding one log in the order_logs table will be triggered
Upvotes: 0
Reputation:
You are mis-understanding what OLD
and NEW
are: those aren't tables, it is the row that has been inserted or modified.
However you do not need to delete and insert everything. Just increment the version in a BEFORE trigger.
Then you can simplify your trigger to:
create or replace function pmigratedatatohistory()
returns trigger as $$
BEGIN
insert into organization_history values (old.*);
new.version := new.version + 1; -- increment the version
return new;
END;
$$
LANGUAGE plpgsql;
You need a BEFORE trigger for that:
create trigger trmigratedatatohistory BEFORE update or delete ON organization
for each row execute procedure pmigratedatatohistory();
The process when you delete a row doesn't make sense to me. The current code does the following:
delete from organization
is executed and the row is deletedafter
trigger, so the row is already gone from the table)The same behaviour can be achieved by the simply incrementing the version in the before trigger. If you want to prevent deletion completely simply return null
in the before trigger:
create or replace function pmigratedatatohistory()
returns trigger as $$
BEGIN
insert into organization_history values (old.*);
new.version := new.version + 1; -- increment the version
if TG_OP = 'DELETE' then
return null; -- "cancel" the delete
else
return new;
endif;
END;
$$
LANGUAGE plpgsql;
Upvotes: 2
Reputation: 246898
For the first INSERT
, use something like
INSERT INTO organization_history VALUES (OLD.*);
The DELETE
and the second INSERT
are ill-conceived – for one, this will cause a lot of unnecessary churn in the organization
table.
It would be much better to use a BEFORE
trigger, add 1 to NEW.version
and return NEW
. This would cause the values to be adjusted before the record is written to the table.
Upvotes: 3