1. 程式人生 > >【Postgresql-9.6.8】觸發器例項(記錄增、刪、改)

【Postgresql-9.6.8】觸發器例項(記錄增、刪、改)

這個觸發器的作用是:當對錶中資料進行INSERT、DELETE、UPDATE時,同時更新另一張表中的相關欄位。

(此例項參考於PG官方文件)

--主表 - 時間維度和銷售事實。
create table time_dimension(
time_key  integer not null,
day_of_week  integer not null,
day_of_month integer not null,
month  integer not null,
quarter  integer not null,
year   integer not null
);
create unique index time_dimension_key on time_dimension(time_key);


create table sales_fact(
time_key  integer not null,
product_key  integer not null,
store_key  integer not null,
amount_sold  numeric(12,2) not null,
units_sold  integer not null,
amount_cost  numeric(12,2) not null
);
create unique index sales_fact_time on sales_fact(time_key);

--彙總表 - 按時間彙總銷售
create table sales_summary_bytime(
time_key  integer not null,
amount_sold  numeric (15,2) not null,
units_sold  numeric(12) not null,
amount_cost  numeric(15,2) not null
);
create unique index sales_summary_bytime_key on sales_summary_bytime(time_key);

--在 UPDATE、INSERT、DELETE 時修改彙總列的函式和觸發器。

create or replace function maint_sales_summary_bytime() returns trigger
as $maint_sales_summary_bytime$
declare
delta_time_key integer;
delta_amount_sold numeric(15,2);
delta_units_sold  numeric(12) ;
delta_amount_cost  numeric(15,2);
begin
--算出增量/減量數。
if (TG_OP='DELETE') then
	delta_time_key=OLD.time_key;
	delta_amount_sold=-1*OLD.amount_sold;
	delta_units_sold=-1*OLD.units_sold;
	delta_amount_cost=-1*OLD.amount_cost;
elsif (TG_OP='UPDATE') then
--禁止更改 the time_key 的更新
-- (可能不會太麻煩,因為大部分的更改是用 DELETE + INSERT 完成的)。
	if (OLD.time_key != NEW.time_key) then
		raise exception 'update of time_key:%->% not allowed',OLD.time_key,NEW.time_key;
	end if;

	delta_time_key=OLD.time_key;
	delta_amount_sold=NEW.amount_sold-OLD.amount_sold;
	delta_units_sold=NEW.units_sold-OLD.units_sold;
	delta_amount_cost=NEW.units_sold-OLD.units_sold;

ELSIF (TG_OP='INSERT') THEN
	delta_time_key=NEW.time_key;
	delta_amount_sold=NEW.amount_sold;
	delta_units_sold=NEW.units_sold;
	delta_amount_cost=NEW.units_sold;
	
END IF;
	
-- 插入或更新帶有新值的彙總行。
<<insert_update>>
loop
	update sales_summary_bytime
		set amount_sold = amount_sold + delta_amount_sold,
		units_sold = units_sold + delta_units_sold,
		amount_cost= amount_cost + delta_amount_cost
	where time_key = delta_time_key;

	exit insert_update when found;

	begin
		insert into sales_summary_bytime (
		time_key,
		amount_sold,
		units_sold,
		amount_cost)
		values(
		delta_time_key,
		delta_amount_sold,
		delta_units_sold,
		delta_amount_cost
		);

		exit insert_update;

	exception
		when unique_violation then
			-- 什麼也不做
	end;
end loop insert_update;
return null;
end;
$maint_sales_summary_bytime$ language plpgsql;

create trigger maint_sales_summary_bytime
after insert or update or delete on sales_fact
	for each row execute procedure maint_sales_summary_bytime();


insert into sales_fact values (1,1,1,10,3,15);
INSERT INTO sales_fact VALUES(2,2,1,40,15,135);
select * from sales_fact;

SELECT * FROM sales_summary_bytime;
DELETE FROM sales_fact WHERE product_key = 1;
SELECT * FROM sales_summary_bytime;
UPDATE sales_fact SET units_sold = units_sold * 2;
SELECT * FROM sales_summary_bytime;