前言今天我們繼續回到mysql系列文章中,談一談mysql中隱式型別轉換。(其實我最早知道是在慢sql優化中知道隱式型別轉換概念的),在說隱式型別轉換之前,首先我們通過乙個例項來看看是怎麼回事。
資料結構
本文中所有的操作,都是基於該資料結構(有興趣的童鞋,可以實驗):
create table t_base_user(
oid bigint(20) not null primary key auto_increment,
name varchar(30) null comment "name",
email varchar(30) null comment "email",
age int null comment "age",
telephone varchar(30) null comment "telephone",
status tinyint(4) null comment "0 無效 1 有效",
created_at datetime null default now() comment "建立時間",
updated_at datetime null default now() comment "修改時間" )
### 新建索引alter table t_base_user add index idx_email(email);
alter table t_base_user add index idx_name(name);
alter table t_base_user add index idx_telephone(telephone);
### 新增記錄:
insert into `andyqian`.`t_base_user` (`name`, `email`, `age`, `telephone`, `status`, `created_at`, `updated_at`)
values ('111111', '[email protected]', '111', '12345678901', '1', now(),now());
引子首先我們基於上述資料結構中,我們來看看下面這個執行計畫:explain select * from t_base_user where telephone=12345678901;
執行計畫結果:
細心的童鞋應該已經看出來了,為什麼資料結構中已經在telephone欄位上新建了idx_telephone索引,而上述語句並沒有走索引,而是全表掃瞄。這是為什麼呢?帶著這疑問,我們來看看今天的主角------mysql隱式型別轉換
什麼隱式型別轉換?
在mysql中:當操作符與不同型別的運算元一起使用時,會發生型別轉換以使運算元相容。則會發生轉換隱式
也就是說,mysql會根據需要自動將數字轉換為字串,將字串轉換數字。看到這個概念之後,是不是有一種茅塞頓開的感覺。哦... 原來在資料結構中telephone欄位為字串(varchar)型別,而我們傳的手機號是數字型別。現在我們將sql修改下:select * from t_base_user where telephone='12345678901';
再看看上述語句的執行計畫:explain select * from t_base_user where telephone='12345678901';
結果:從這裡看,現在語句已經走索引了。為了加深我們對隱式型別轉換的印象,我們再多看看幾個隱式型別轉換案例:
案例一: 字串轉換為數字mysql > select 1+'1';
結果:mysql > 2
案例二: 數字轉換為字串mysql -> select concat(1024,' andyqian');
結果:'1024,' andyqian';
此時concat(字元拼接)函式就將1024進行了隱式型別轉換。
如何避免隱式型別轉換?
只有當清楚的知道隱式型別轉換的規則,才能從根本上避免產生隱式型別轉換。mysql也在官網描述了進行隱式型別轉換的一些規則如下:
1. 隱式型別轉換規則:如果乙個或兩個引數都是null,比較的結果是null,除了null安全的<=>相等比較運算子。對於null <=> null,結果為true。不需要轉換
如果比較操作中的兩個引數都是字串,則將它們作為字串進行比較。
如果兩個引數都是整數,則將它們作為整數進行比較。
如果不與數字進行比較,則將十六進製制值視為二進位制字串
如果其中乙個引數是十進位制值,則比較取決於另乙個引數。 如果另乙個引數是十進位制或整數值,則將引數與十進位制值進行比較,如果另乙個引數是浮點值,則將引數與浮點值進行比較
如果其中乙個引數是timestamp或datetime列,另乙個引數是常量,則在執行比較之前將常量轉換為時間戳。
在所有其他情況下,引數都是作為浮點數(實數)比較的。
2. 使用cast函式顯示轉換
我們可以使用cast顯示的將型別進行轉換,如下所示:mysql> select 38.8, cast(38.8 as char);
結果:mysql > 38.8, '38.8'
如上述中:select * from t_base_user where telephone=cast(12345678901 as char);
檢視執行計畫,我們也可以看出
你看,這個時候也走索引了。
3. 型別一致
這裡說的型別一致,指的是在寫sql時,引數型別一定要與資料庫中的型別一致,避免產生隱式型別轉換,就如剛才在文首時,如果多檢查,寫的sql的引數型別與資料庫中欄位型別一致,也就不會不走索引了,你說是不是?
小心隱式型別轉換
這裡再重申一次,寫sql時一定要檢查引數型別與資料庫字段型別一致,(如果引數不一致,也要使用cast函式顯示轉換成一致)否則造成隱式型別轉換,不走索引,後果簡直不堪設想, 在前面《寫會mysql索引》這篇文章中提到過,不走索引,輕則造成慢查詢,重則造成資料庫伺服器cpu100%。唉,說到這裡,不瞞你說,我就吃過不少mysql隱式型別轉換的虧 ! (如慢查詢) !
小結看到這裡,是不是有一種,資料表設計還真不是件容易的事情。需要考慮的因素太多太多了,需要考慮字段型別,索引設計,還有各種約束條件等等。也一定要謹慎謹慎再謹慎!其實換個角度就更容易理解了,大家都知道高樓大廈都是需要乙個好的地基的,在資料庫表設計中,前期的表結構設計就是這個地基,其重要性可想而知。
今天的命令是:show full columns from table_name;
作用: 顯示指定表所有列資訊
例如:show full columns from t_base_user;
返回結果如下圖所示:
其中:field: 欄位名
type: 該欄位型別
collation: 描述了如何對查詢出來的資料進行比較和排序
null: 是否允許為空, no: 不允許,yes 允許
key: 鍵,例如: 主鍵(pri), 唯一鍵(uni) 等
default: 該欄位預設值 extra: 附加資訊如自增主鍵上的(auto_increment)
privileges: 許可權,有select,update等
comment: 字段注釋
注意: 通過該命令顯示都是建表時的資訊,這裡著重強調一下,在資料庫建表時,在每個欄位上, 一定要加注釋,加注釋,加注釋!
最後:大家今天剁手了嗎? 祝大家晚安!
mysql 隱式轉換 mysql中的隱式轉換
在mysql查詢中,當查詢條件左右兩側型別不匹配的時候會發生隱式轉換,可能導致查詢無法使用索引。下面分析兩種隱式轉換的情況 看表結構 phone為 int型別,name為 varchar 兩種情況都可以用到索引,這次等號右側是 2 注意帶單引號喲,左側的索引欄位是int型別,因此也會發生隱式轉換,但...
mysql隱式轉換
定義 當操作符與不同型別的運算元一起使用時,會發生型別轉換以使運算元相容。則會發生轉換隱式 舉乙個常見例子 1 我們先建立乙個表,有關手機號查詢 create table user id int 11 not null primary keyauto increment phone varchar ...
mysql隱式轉換
create table testsql id int 11 name varchar 11 descid varchar 11 alter table testsql add index descid alter table testsql add unique id insert into te...