MySQL 5.7支持為表增加計(jì)算列
什么叫計(jì)算列呢,簡(jiǎn)單來說就是某一列的值是通過別的列計(jì)算得來,例如a列值為1,b列值為2梗劫,c列不需要手動(dòng)操作插入,定義c的值為a + b的結(jié)果截碴,那么c就是計(jì)算列在跳,是通過別的列計(jì)算得來,下面我們進(jìn)行例子說明:
在MySQL 5.7之前的版本中隐岛,要實(shí)現(xiàn)這樣的效果得利用觸發(fā)器來完成,以下是以前的實(shí)現(xiàn)過程:
mysql> show create table tb1\G
*************************** 1. row ***************************
?????? Table: tb1
Create Table: CREATE TABLE `tb1` (
??`id` int(11) NOT NULL AUTO_INCREMENT,
??`c1` int(11) DEFAULT NULL,
??`c2` int(11) DEFAULT NULL,
??`c3` int(11) DEFAULT NULL,
??PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.01 sec)
創(chuàng)建一個(gè)插入的觸發(fā)器:
mysql> create trigger insert_tb1 before insert on tb1 for each row set new.c3=new.c1+new.c2;
Query OK, 0 rows affected (0.01 sec)
我們插入數(shù)據(jù):
mysql> insert into tb1(c1,c2) values (1,2);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tb1;
+----+------+------+------+
| id | c1?? | c2?? | c3?? |
+----+------+------+------+
|??1 |????1 |????2 |????3 |
+----+------+------+------+
1 row in set (0.00 sec)
但如果我們更新了c1或者c2的值瓷翻,c3是不會(huì)變動(dòng)的聚凹,所以我們要加一個(gè)update的觸發(fā)器:
mysql> select * from tb1;
+----+------+------+------+
| id | c1?? | c2?? | c3?? |
+----+------+------+------+
|??1 |????1 |????2 |????3 |
+----+------+------+------+
1 row in set (0.00 sec)
mysql>??create trigger update_tb1 before update on tb1 for each row set new.c3=new.c1+new.c2;??????????
Query OK, 0 rows affected (0.01 sec)
mysql> update tb1 set c1 = 3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1??Changed: 1??Warnings: 0
mysql> select * from tb1;
+----+------+------+------+
| id | c1?? | c2?? | c3?? |
+----+------+------+------+
|??1 |????3 |????2 |????5 |
+----+------+------+------+
1 row in set (0.00 sec)
可以看到,如果想實(shí)現(xiàn)計(jì)算列齐帚,那么就要借助觸發(fā)器或者視圖來實(shí)現(xiàn)妒牙,但在生產(chǎn)環(huán)境中,是不太建議使用觸發(fā)器或者視圖的对妄。下面用MySQL 5.7來實(shí)現(xiàn)就變得很簡(jiǎn)單了湘今。
MySQL 5.7計(jì)算列的實(shí)現(xiàn):
在CREAE TABLE和ALTER TABLE?中都支持增加計(jì)算列的方式:
col_name data_type [GENERATED ALWAYS] AS (expression)
??????[VIRTUAL | STORED] [UNIQUE [KEY]] [COMMENT comment]
??????[NOT NULL | NULL] [[PRIMARY] KEY]
下面我們創(chuàng)建測(cè)試表tb2:
mysql> show create table tb2\G??
*************************** 1. row ***************************
?????? Table: tb2
Create Table: CREATE TABLE `tb2` (
??`id` int(11) NOT NULL AUTO_INCREMENT,
??`c1` int(11) DEFAULT NULL,
??`c2` int(11) DEFAULT NULL,
??`c3` int(11) GENERATED ALWAYS AS ((`c1` + `c2`)) VIRTUAL,
??PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.00 sec)
插入數(shù)據(jù)看效果:
mysql> select * from tb2;
Empty set (0.00 sec)
mysql> insert into tb2(c1,c2) values (1,2);
Query OK, 1 row affected (0.00 sec)
mysql> select * from tb2;
+----+------+------+------+
| id | c1?? | c2?? | c3?? |
+----+------+------+------+
|??1 |????1 |????2 |????3 |
+----+------+------+------+
1 row in set (0.00 sec)
更新數(shù)據(jù)看效果:
mysql> update tb2 set c1=10;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1??Changed: 1??Warnings: 0
mysql> select * from tb2;
+----+------+------+------+
| id | c1?? | c2?? | c3?? |
+----+------+------+------+
|??1 |?? 10 |????2 |?? 12 |
+----+------+------+------+
1 row in set (0.00 sec)
可以看到相當(dāng)?shù)姆奖悖琈ySQL 5.7的很多新特性都給我們帶來了便利和驚喜^.^剪菱。
在MySQL 5.7中摩瞎,支持兩種generated column拴签,即virtual generated column和stored generated column,前者只將generated column保存在數(shù)據(jù)字典中(表的元數(shù)據(jù))旗们,并不會(huì)將這一列數(shù)據(jù)持久化到磁盤上蚓哩;后者會(huì)將generated column持久化到磁盤上,而不是每次讀取的時(shí)候計(jì)算所得上渴。很明顯岸梨,后者存放了可以通過已有數(shù)據(jù)計(jì)算而得的數(shù)據(jù),需要更多的磁盤空間稠氮,與virtual column相比并沒有優(yōu)勢(shì)曹阔。因此,在不指定generated column的類型時(shí)隔披,默認(rèn)是virtual column赃份。
如果讀者覺得generate column提供的功能,也可以在用戶代碼里面實(shí)現(xiàn)锹锰,并沒有什么了不起的地方芥炭,那么,或許還有一個(gè)功能能夠吸引挑剔的你恃慧,那就是為generate column創(chuàng)建索引园蝠。在這個(gè)例子中,如果我們需要根據(jù)generate column創(chuàng)建索引以加快查詢痢士,就無法在用戶代碼里面實(shí)現(xiàn)彪薛,使用generate column就變得非常簡(jiǎn)單:
mysql> alter table tb2 add index ix_c3(c3);
mysql> explain select * from tb2 where c3=10;
+----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key? | key_len | ref? | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------+
|? 1 | SIMPLE? ? ? | tb2? | NULL? ? ? | ref? | ix_c3? ? ? ? | ix_c3 | 5? ? ? | const |? ? 1 |? 100.00 | NULL? |
+----+-------------+-------+------------+------+---------------+-------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
參考資料:運(yùn)維那點(diǎn)事