存儲引擎決定了表的類型, 而表內存放的數據也是有不一樣的類型, MySQL支持多種類型, 大體能夠分爲三類 : 數值類型、日期類型、字符串類型html
關鍵字INT是INTEGER的同義詞,關鍵字DEC是DECIMAL的同義詞python
做用 : 存儲年齡、等級、ID、各類號碼等 (如下介紹幾種經常使用整數類型)mysql
tinyint[(m)] [unsigned(無符號)] [zerofill(零填充)]
🍓默認有符號演示 create table t01(id tinyint); # 建立一個表, id字段類型tinyint,有符號 desc t01; # 查看錶結構, "describe t01" insert table t01 values(-129),(-128),(128),(127); # 插入四條記錄 show * from t01; # 查看錶內容
🍓無符號演示 create table t02(id tinyint unsigned); # 建立一個表, 設置無符號 insert table t01 values(-2),(0),(255),(636); # 插入四條記錄 select * from t02; # 查看錶內容
int[(m)][unsigned(無符號)] [zerofill(零填充)]
🍓默認有符號演示 create table t03(id int) charset utf8; # 建立一個表, 默認有符號 desc t03; # 查看該表結構 insert into t03 values(-2147483649),(-2147483648),(2147483647),(2147483648); # 插入記錄 select id from t03; # 查看錶內容 🍓無符號演示 create table t04(id int unsigned); # 建立一個表, 無符號 insert into t04 values(-3),(0),(4294967295),(4294967296); # 插入四條記錄 select id from t04; # 查看錶內容
bigint[(m)][unsigned(無符號)] [zerofill(零填充)]
🍓默認有符號演示 create table t05(id bigint); # 建立一個表, 默認有符號 desc t05; # 查看一下表結構 insert into t05 values(-9223372036854775809),(-9223372036854775808),(9223372036854775807),(9223372036854775808); # 插入四條記錄 select id from t05; # 查看錶內容 🍓無符號演示 create table t06(id bigint unsigned); # 建立一個表, 無符號 insert into t06 values(-1),(0),(18446744073709551615),( 18446744073709551617); # 插入四條記錄 select id from t06; # 查看錶內容
create table t07(id int(3) zerofill); # 建立一個表, 設置字段類型並設置顯示寬度爲3, 不足以0填充 insert into t07 values(1),(11),(111),(1111); # 插入四條記錄 select id from t07; # 查看錶內容
由上面的測試能夠發現, 爲整形類型指定寬度時, 指定的僅僅是查詢結果時的寬度, 與存儲的範圍沒有關係, 存儲範圍以下, 其實咱們徹底不必爲整數類型指定顯示寬度, 使用默認的就能夠了sql
🍓默認寬度說明 int的存儲寬度是4個Bytes,即32個bit,即2**32 無符號最大值爲:4294967296-1, 有符號最大值:2147483648-1 有符號和無符號的最大數字須要的顯示寬度均爲10 而針對有符號的最小值則須要 11 位才能顯示徹底 因此int類型默認的顯示寬度爲 11
結論 : 非嚴格模式下數據庫
做用 : 儲存薪資、身高、體重、體質參數等網絡
FLOAT[(m,d)] [UNSIGNED(無符號)] [ZEROFILL(0填充)]
create database test05 charset utf8; # 建立一個新的數據庫來作實驗 create table t01(x,float(255,30)) # 建立一個float類型的表,精度取最大範圍(後面演示超出範圍會怎樣) insert into t01 values(1.1111111111111111111111111111111); # 插入一條數據, 小數點後31個1 select * from t01; # 查看錶內容
DOUBLE[(m,d)] [UNSIGNED(無符號)] [ZEROFILL(0填充)]
create table t02(x double(255,30)); # 建立一個double類型的表, 精度取最大值 insert into t02 values(1.1111111111111111111111111111111); # 插入一條數據, 小數點後31個1 select * from t02; # 查看錶內容
參數 : DECIMAL[(m,d)] [UNSIGNED(無符號)] [ZEROFILL(0填充)]
函數
定義 : 準確的小數值, m是數字總個數(負號不算)最大值爲65, d是小數點後個數最大值爲30測試
精準度 : 隨着小數的增多, 精度始終準確ui
對於精確數值計算時須要用此類型, decaimal 可以存儲精確值的緣由在於其內部按照字符串存儲編碼
create table t03(x decimal(65,30)); # 建立一個decimal類型的表, 精度取最大值 insert into t03 values(1.1111111111111111111111111111111); # 插入一條數據, 小數點後31個1 select * from t03; # 查看錶內容
類型 : DATE、TIME、DATETIME、TIMESTAMP、YEAR
做用 : 存儲用戶註冊時間,文章發佈時間,員工入職時間,出生時間,過時時間等
範圍限制 : 如上圖, 每一個類型都有範圍, 超出範圍的mysql將自動設置成 "零" 值
now( ) : 當前時間
create table t05(from_year year); # 不管year指定何種寬度,最後都默認是year(4) insert into t05 values(1111),(1901),(2155),(2222); # 插入四條年份記錄 select * from t05; # 查看錶內容
create table t06(D date,T time,DT datetime); # 建立表 desc t06; # 查看下錶結構 insert into t06 values(now(),now(),now()); # 插入一條記錄 select * from t06; # 查看錶內容
create table t07(TS timestamp); insert into t07 values(); # 傳空 insert into t07 values(null); # 傳空 select * from t07;
datetime的日期範圍是1001--9999, timstamp的時間範圍是1970--2038年
timestamp字段比datetime字段的空間利用率更高, 存取速度更快
timestamp字段比datetime字段建表的時候更方便
datetime的默認值爲null, timestamp的字段默認不爲空(not null), 默認值爲當前時間, 若是不作特殊處理, 而且update語句中沒有指定該列的更新值, 則默認更新爲當前時間
create table t08(DT datetime not null default now()); # 指定傳空時默認取當前時間 create table t09(TS timestamp); # 不須要指定,再傳空時自動傳入當前時間 insert into t08 values(); # 傳空 insert into t09 values(); # 傳空 select * from t08; # 查看錶內容 select * from t09; # 查看錶內容
datetime 自動填充時間須要指定not null default now( ), 通常用於註冊等定格的時間, 若是想用做更新時間就得指定on update now( ), 而timestamp自帶此功能
create table t10(name varchar(5),T datetime not null default now()); # 建立兩個字段的表 create table t11(name varchar(5),T datetime not null default now() on update now()); # 添加了時間更新功能 create table t12(name varchar(5),T timestamp); # 自帶更新時間功能 desc t10; # 分別查看一下三個表結構 desc t11; desc t12; insert into t10(name) values("shawn"); # 插入name字段的記錄, 讓T字段自動填充 insert into t11(name) values("shawn"); insert into t12(name) values("shawn"); select * from t10; # 分別查看一下三表的內容, 注意一下三表的時間 select * from t11; select * from t12; update t10 set name="song" where name="shawn"; # 對三表的name字段記錄進行修改 update t11 set name="song" where name="shawn"; update t12 set name="song" where name="shawn"; select * from t10; # 再次查看三表內容, 注意查看三表的時間變化 select * from t11; select * from t12;
字符串類型有不少, 這裏只介紹 CHAR、VARCHAR兩種類型, 更多可參考https://www.runoob.com/mysql/mysql-data-types.html
注意 : char 和 varchar 括號內的參數值的都是字符的長度, 不是字節長度
ps : 對於MySQL 4.1以前的版本,如 MySQL 3.23 和 MySQL 4.0, CHAR(N)和 VARCHAR (N)中的 N 表明字節長度
SET sql_mode = 'pad_char_to_full_length';
)下邊將使用到的函數 :
- hex( ) : 將傳入的字符串貨數字轉成十六進制格式的字符串
- length( ) : 返回傳入內容的字節長度, utf8 編碼英文 1 字節,中文 3 字節, gbk英文都 1 字節,中文 2 字節
- char_length( ) : 返回傳入內容的字符長度
UTF8編碼測試
create database test01 charset utf8; # 建立一個新庫作測試 use test01; # 進入庫 create table t01(n char(10)); # 建立一個表,n字段char類型規定10字符長度 insert into t01 values("abc 你好 "); # 插入"abc 你好 " select n,hex(n),length(n),char_length(n) from t01; # 查看錶內容,還有長度
SET sql_mode = 'pad_char_to_full_length';
GBK編碼測試
create database test02 charset gbk; # 建立一個新庫,gbk編碼 use test02; # 進入庫 create table t01(n char(10)); #建立表, n字段char類型規定10長度 insert into t01 values("abc 你好 "); # 插入"abc 你好 " select n,hex(n),length(n),char_length(n) from t01; # 查看錶內容和內容長度 set sql_mode='pad_char_to_full_length'; # 設置SQL模式,空格填充 select n,hex(n),length(n),char_length(n) from t01; # 再次查看變化
超出規定字符數測試
insert into t01 values("abc 你好 aaaaaaaaaaaaaaaaaaaa"); select n,hex(n),length(n),char_length(n) from t01;
create database test04 charset utf8; use test04; create table t01(x char(10),y varchar(10)); # 建立表, 設置兩個字段使用不一樣的類型規定長度爲10 insert t01 values("1111","1111"); select * from t01; set sql_mode='pad_char_to_full_length'; # 設置SQL模式, 空格填充 select * from t01;
select x,y,length(x),length(y) from t01; # 查看字符長度
Value | CHAR(4) |
Storage Required | VARCHAR(4) |
Storage Required |
---|---|---|---|---|
'' |
' ' |
4 bytes | '' |
1 byte |
'ab' |
'ab ' |
4 bytes | 'ab' |
3 bytes |
'abcd' |
'abcd' |
4 bytes | 'abcd' |
5 bytes |
'abcdefgh' |
'abcd' |
4 bytes | 'abcd' |
5 bytes |
- char填充空格來知足固定長度,可是在查詢顯示時卻會刪除尾部的空格(裝做本身好像沒有浪費過空間同樣), 能夠修改sql_mode讓其現出原形
- varchar存的是真實長度+1~2Bytes說明信息(相似於頭)
- 存數據時, 在非嚴格模式下, 字符數超過了或者剛剛等於指定得寬度 , char類型更加節省空間
- 字符數小於指定得寬度varchar類型, 更加節省空間, 基於網絡IO得狀況, varchar更好,
char、varchar如何選擇 :
- 對於MyISAM表,儘可能使用Char: 對於那些常常須要修改而容易造成碎片的myisam和isam數據表就更是如此,它的缺點就是佔用磁盤空間
- 對於InnoDB表,儘可能使用varVhar: 由於它的數據行內部存儲格式對固定長度的數據行和可變長度的數據行不加區分(全部數據行共用一個表頭部分,這個標頭部分存放着指向各有關數據列的指針),因此使用char類型不見得會比使用varchar類型好。事實上,由於char類型一般要比varchar類型佔用更多的空間,因此從減小空間佔用量和減小磁盤i/o的角度,使用varchar類型反而更有利
- 存儲很短的信息,儘可能使用Char: 好比門牌號碼101, 20....這樣很短的信息應該用char,由於varchar還要 佔個byte用於存儲信息長度,原本打算節約存儲的如今得不償失
- 固定長度的數據, 儘可能使用Char: 好比使用uuid做爲主鍵,那用char應該更合適。由於他固定長度,varchar動態根據長度的特性就消失了,並且還要佔個長度信息
- 十分頻繁改變的字段列, 儘可能使用varchar: 由於varchar每次存儲都要 有額外的計算,獲得長度等工做,若是一個很是頻繁改變的,那就要有不少的精力用於計算,而這些對於char來講是不須要的。
做用 : 讓字段的值只能在給定的範圍內進行選擇 : 多選, 單選
create table t03(name varchar(10),sex enum("male","female","eunuch")); insert t03(name,sex) values("shawn","male"); # 選擇一個性別 select sex from t03;
insert t03 values("song","wooo"); # 插入一條記錄, sex字段選擇一個不存在的選項 select * from t03;
create table t04(name varchar(10),hobby set("read","run","eat","sleep","play")); insert t04 values("shawn","read,run"),("song","run,sleep,play"); select * from t04;
存一個員工的id、姓名、年齡、身高、性別、愛好(這裏提供愛好選項)、家庭住址、入職時間、每個月收入、信息最近修改時間, 選擇合適的類型
create table info( id int, name char(16), age tinyint, height float, sex enum("male","female"), hobby set("read","run","eat","sleep","play"), home_addr varchar(16), entry_time datetime not null default now(), salary double(255,3), info_change_time timestamp ); insert info values(01,"shawn",22,1.72,"male","read,sleep","上海市青浦區",now(),15000.53,now()); insert info values(02,"pai",23,1.82,"female","read,play","上海市黃浦區",now(),1000.342,now()); insert info values(03,"da",44,1.62,"female","run,eat,sleep","北京天安門前",now(),9000,now()); insert info values(04,"xing",25,1.52,"male","play,sleep","美國巴黎",now(),35000.53,now());
update info set name="派大星" where name="xing"; # 更新一個字段 select * from info; # 查看是否變化