mysql触发器实现oracle物化视图功能

本文介绍了如何在MySQL中通过触发器来模拟Oracle数据库中的物化视图功能,包括创建on demand的物化视图以及利用触发器实现on commit的实时更新。示例展示了在基表上进行DML操作后,如何自动更新物化视图以保持同步。
摘要由CSDN通过智能技术生成

oracle数据库支持物化视图,是根据基表实际存在的实表,物化视图可以用于预先计算并保存多表的链接(JOIN)
或聚集(GROUP BY)等耗时较多的SQL操作结果,sql server 叫做索引视图。
物化视图的刷新是指当基表发生DML操作,物化视图何时采用哪种方式和基表进行同步:
on demand
on commit
mysql本事不支持物化视图,但是可以通过一些机制实现实现物化视图的功能,例如创建一个on demand的物化视图:

mysql> create table orders(
-> order_id int unsigned not null auto_increment,
-> product_name varchar(30) not null,
-> price decimal(8,2) not null,
-> amount smallint not null,
-> primary key (order_id)
-> )engine=innodb;

mysql> select * from orders;
±---------±-------------±-------±-------+
| order_id | product_name | price | amount |
±---------±-------------±-------±-------+
| 1 | CPU | 135.00 | 1 |
| 2 | MEMORY | 48.00 | 3 |
| 3 | CPU | 126.00 | 3 |
| 4 | CPU | 105.00 | 4 |
±---------±-------------±-------±-------+

mysql> create table orders_mv(
-> product_name varchar(30) not null,
-> price_sum decimal(8,2) not null,
-> amount_sum int not null,
-> price_avg float not null,
-> orders_cnt int not null,
-> unique index(product_name)
-> );

mysql> insert into orders_mv select product_name ,sum(price),sum(amount),avg(price),count(*) from orders group by product_name;
Query OK, 2 rows affected (0.01 sec)

mysql> select * from orders_mv;
±-------------±----------±-----------±----------±-----------+
| product_name | price_sum | amount_sum | price_avg | orders_cnt |
±-------------±----------±-----------±----------±-----------+
| CPU | 366.00 | 8 | 122 | 3 |
| MEMORY | 48.00 | 3 | 48 | 1 |
±-------------±----------±-----------±----------±-----------+



但是要是实现 on commit 的物化视图,就没这么简单了,Oracle通过物化视图日志来实现,
mysql通过触发器同样可以达到这个目的:

mysql> \d m y s q l > c r e a t e t r i g g e r p 1 a f t e r i n s e r t o n o r d e r s − > f o r e a c h r o w − > b e g i n − > s e t @ o l d p r i c e s u m = 0 ; − > s e t @ o l d a m o u n t s u m = 0 ; − > s e t @ o l d p r i c e a v g = 0 ; − > s e t @ o l d o r d e r s c n t = 0 ; − > s e l e c t i f n u l l ( p r i c e s u m , 0 ) , i f n u l l ( a m o u n t s u m , 0 ) , i f n u l l ( p r i c e a v g , 0 ) , i f n u l l ( o r d e r s c n t , 0 ) − > f r o m o r d e r s m v − > w h e r e p r o d u c t n a m e = n e w . p r o d u c t n a m e − > i n t o @ o l d p r i c e s u m , @ o l d a m o u n t s u m , @ o l d p r i c e a v g , @ o l d o r d e r s c n t ; − > s e t @ n e w p r i c e s u m = @ o l d p r i c e s u m + n e w . p r i c e ; − > s e t @ n e w a m o u n t s u m = @ o l d a m o u n t s u m + n e w . a m o u n t ; − > s e t @ n e w o r d e r s c n t = @ o l d o r d e r s c n t + 1 ; − > s e t @ n e w p r i c e a v g = @ n e w p r i c e s u m / @ n e w o r d e r s c n t ; − > r e p l a c e i n t o o r d e r s m v − > v a l u e s ( n e w . p r o d u c t n a m e , @ n e w p r i c e s u m , @ n e w a m o u n t s u m , @ n e w p r i c e a v g , @ n e w o r d e r s c n t ) ; − > e n d ; − > mysql> create trigger p1 after insert on orders -> for each row -> begin -> set @old_price_sum=0; -> set @old_amount_sum=0; -> set @old_price_avg=0; -> set @old_orders_cnt=0; -> select ifnull(price_sum,0),ifnull(amount_sum,0),ifnull(price_avg,0),ifnull(orders_cnt,0) -> from orders_mv -> where product_name=new.product_name -> into @old_price_sum,@old_amount_sum,@old_price_avg,@old_orders_cnt; -> set @new_price_sum=@old_price_sum + new.price; -> set @new_amount_sum=@old_amount_sum + new.amount; -> set @new_orders_cnt=@old_orders_cnt +1; -> set @new_price_avg=@new_price_sum / @new_orders_cnt; -> replace into orders_mv -> values(new.product_name,@new_price_sum,@new_amount_sum,@new_price_avg,@new_orders_cnt); -> end; -> mysql>createtriggerp1afterinsertonorders>foreachrow>begin>set@oldpricesum=0;>set@oldamountsum=0;>set@oldpriceavg=0;>set@oldorderscnt=0;>selectifnull(pricesum,0),ifnull(amountsum,0),ifnull(priceavg,0),ifnull(orderscnt,0)>fromordersmv>whereproductname=new.productname>into@oldpricesum,@oldamountsum,@oldpriceavg,@oldorderscnt;>set@newpricesum=@oldpricesum+new.price;>set@newamountsum=@oldamountsum+new.amount;>set@neworderscnt=@oldorderscnt+1;>set@newpriceavg=@newpricesum/@neworderscnt;>replaceintoordersmv>values(new.productname,@newpricesum,@newamountsum,@newpriceavg,@neworderscnt);>end;>

insert into orders values(NULL,‘SSD’,299,3);

mysql> select *from orders;
±---------±-------------±-------±-------+
| order_id | product_name | price | amount |
±---------±-------------±-------±-------+
| 1 | CPU | 135.00 | 1 |
| 2 | MEMORY | 48.00 | 3 |
| 3 | CPU | 126.00 | 3 |
| 4 | CPU | 105.00 | 4 |
| 11 | SSD | 299.00 | 3 |
±---------±-------------±-------±-------+
5 rows in set (0.00 sec)

mysql> select * from orders_mv;
±-------------±----------±-----------±----------±-----------+
| product_name | price_sum | amount_sum | price_avg | orders_cnt |
±-------------±----------±-----------±----------±-----------+
| CPU | 366.00 | 8 | 122 | 3 |
| MEMORY | 48.00 | 3 | 48 | 1 |
| SSD | 299.00 | 3 | 299 | 1 |
±-------------±----------±-----------±----------±-----------+

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值