🍖表數據類型詳解

引入

存儲引擎決定了表的類型, 而表內存放的數據也是有不一樣的類型, MySQL支持多種類型, 大體能夠分爲三類 : 數值類型、日期類型、字符串類型html

一.數值類型

關鍵字INT是INTEGER的同義詞,關鍵字DEC是DECIMAL的同義詞python

image-20210130175607997

二.數值類型之整數類型

  • TINYINT : 小整數
  • SAMLLINT : 短整數
  • MEDIUMINT : 中整數
  • INT 或 INTEGER : 整數
  • BIGINT : 大整數

做用 : 存儲年齡、等級、ID、各類號碼等 (如下介紹幾種經常使用整數類型)mysql

1.TINYINT (小整數)

  • 參數 : tinyint[(m)] [unsigned(無符號)] [zerofill(零填充)]
  • 有符號整數範圍(-128~127), 無符號整數範圍(0~255), 默認有符號
🍓默認有符號演示
create table t01(id tinyint);  # 建立一個表, id字段類型tinyint,有符號
desc t01;         # 查看錶結構, "describe t01"
insert table t01 values(-129),(-128),(128),(127);  # 插入四條記錄
show * from t01;  # 查看錶內容

image-20210130202948683

image-20210130203234875

🍓無符號演示
create table t02(id tinyint unsigned);        # 建立一個表, 設置無符號
insert table t01 values(-2),(0),(255),(636);  # 插入四條記錄
select * from t02;  # 查看錶內容

image-20210130204723636

2.INT | INTEGER (整數)

  • 參數 : int[(m)][unsigned(無符號)] [zerofill(零填充)]
  • 有符號範圍 : (-2147483648~2147483647), 無符號範圍 : (0~4294967295), 默認有符號
🍓默認有符號演示
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;  # 查看錶內容

3.BIGINT (大整數)

  • 參數 : bigint[(m)][unsigned(無符號)] [zerofill(零填充)]
  • 有符號範圍 : (-9223372036854775808~9223372036854775807)
  • 無符號範圍 : ( 0~18446744073709551615) 默認有符號
🍓默認有符號演示
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;     # 查看錶內容

4.zerofill 參數測試整數類型的顯示寬度

create table t07(id int(3) zerofill);  # 建立一個表, 設置字段類型並設置顯示寬度爲3, 不足以0填充
insert into t07 values(1),(11),(111),(1111);  # 插入四條記錄
select id from t07;  # 查看錶內容

image-20210130212052506

由上面的測試能夠發現, 爲整形類型指定寬度時, 指定的僅僅是查詢結果時的寬度, 與存儲的範圍沒有關係, 存儲範圍以下, 其實咱們徹底不必爲整數類型指定顯示寬度, 使用默認的就能夠了sql

🍓默認寬度說明
int的存儲寬度是4個Bytes,即32個bit,即2**32
無符號最大值爲:4294967296-1, 有符號最大值:2147483648-1
有符號和無符號的最大數字須要的顯示寬度均爲10
而針對有符號的最小值則須要 11 位才能顯示徹底
因此int類型默認的顯示寬度爲 11

結論 : 非嚴格模式下數據庫

  • 若是數字沒有超出括號內指定的長度, 那麼默認用 0 填充至括號內的長度
  • 若是數字超出括號內指定的長度, 那麼有幾位就存幾位,但仍是不能超過最大範圍, 超過則顯示該類型的最大值(上面已經測試過了) (若是是嚴格模式下,超出了範圍直接報錯)

三.數值類型之浮點型

  • FLOAT : 單精度浮點數
  • DOUBLE : 雙精度浮點數
  • DEC 或 DECIMAL : 準確小數值

做用 : 儲存薪資、身高、體重、體質參數等網絡

1.FLOAT (單精度浮點數)

  • 參數 : FLOAT[(m,d)] [UNSIGNED(無符號)] [ZEROFILL(0填充)]
  • 定義 : 單精度浮點數(非準確小數值), m是數字總個數最大值爲255d是小數點後個數最大值爲30, 整數部分225
  • 有符號範圍 : -3.402823466E+38 to -1.175494351E-38, 1.175494351E-38 to 3.402823466E+38
  • 無符號範圍 : 1.175494351E-38 to 3.402823466E+38
  • 精準度 : 隨着小數的增多, 精度變得不許確
create database test05 charset utf8;  # 建立一個新的數據庫來作實驗
create table t01(x,float(255,30))  # 建立一個float類型的表,精度取最大範圍(後面演示超出範圍會怎樣)
insert into t01 values(1.1111111111111111111111111111111);  # 插入一條數據, 小數點後31個1
select * from t01;  # 查看錶內容

image-20210130222905238

2.DOUBLE (雙精度浮點數)

  • 參數 : DOUBLE[(m,d)] [UNSIGNED(無符號)] [ZEROFILL(0填充)]
  • 定義 : 雙精度浮點數(非準確小數值), m是數字總個數最大值爲255d是小數點後個數最大值爲30, 整數部分225
  • 有符號範圍 : -1.7976931348623157E+308 to -2.2250738585072014E-308, 2.2250738585072014E-308 to 1.7976931348623157E+308
  • 無符號範圍 : 2.2250738585072014E-308 to 1.7976931348623157E+308
  • 精準度 : 隨着小數的增多, 精度比float要高, 但也會變得不許確
create table t02(x double(255,30));  # 建立一個double類型的表, 精度取最大值
insert into t02 values(1.1111111111111111111111111111111);  # 插入一條數據, 小數點後31個1
select * from t02;  # 查看錶內容

image-20210130224001583

3.DECIMAL (準確小數值)

  • 參數 : 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;  # 查看錶內容

image-20210130225113040

四.日期和時間類型

image-20210130225430645

  • 類型 : DATE、TIME、DATETIME、TIMESTAMP、YEAR

  • 做用 : 存儲用戶註冊時間,文章發佈時間,員工入職時間,出生時間,過時時間等

  • 範圍限制 : 如上圖, 每一個類型都有範圍, 超出範圍的mysql將自動設置成 "零"

  • now( ) : 當前時間

1.YEAR (年)測試

  • 範圍 : 1901~2155
create table t05(from_year year);  # 不管year指定何種寬度,最後都默認是year(4)
insert into t05 values(1111),(1901),(2155),(2222);  # 插入四條年份記錄
select * from t05;  # 查看錶內容

image-20210130230805178

2.DATE、TIME、DATETIME(日期, 時間值, 混合日期時間)演示

create table t06(D date,T time,DT datetime);  # 建立表
desc t06;  # 查看下錶結構
insert into t06 values(now(),now(),now());  # 插入一條記錄
select * from t06;  # 查看錶內容

image-20210130231801218

3.TIMESTAMP (混合日期和時間) 演示

  • 特色 : 傳空的狀況下自動傳入當前時間, 自動更新時間
create table t07(TS timestamp);
insert into t07 values();     # 傳空
insert into t07 values(null); # 傳空
select * from t07;

image-20210130232919655

4.datatime 與 timestamp 的區別

  • 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;         # 查看錶內容

image-20210130234909040

datetime 自動填充時間須要指定not null default now( ), 通常用於註冊等定格的時間, 若是想用做更新時間就得指定on update now( ), 而timestamp自帶此功能

  • on update now( ) 功能演示
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;

image-20210131001028765

image-20210131001310692

image-20210131001612812

五.字符串類型

字符串類型有不少, 這裏只介紹 CHAR、VARCHAR兩種類型, 更多可參考https://www.runoob.com/mysql/mysql-data-types.html

image-20210131083715391

注意 : char 和 varchar 括號內的參數值的都是字符的長度, 不是字節長度

ps : 對於MySQL 4.1以前的版本,如 MySQL 3.23 和 MySQL 4.0, CHAR(N)和 VARCHAR (N)中的 N 表明字節長度

1.CHAR 類型

  • 特色 : 定長, 存儲簡單, 耗費空間, 但存取速度快
  • 字符長度範圍 : CHAR(N)用來保存固定長度的字符串, N 的範圍 爲 (0 ~ 255)
  • 存儲特色 : 存儲char類型的值時, 會往右填充空格來知足你指定的字符長度, 例如指定長度爲5, 存大於5字符報錯, 小於5就以空格填充到5個字符存儲
  • 查詢 : 在檢索(查詢)時, 查出的結果會自動刪除尾部的空格, (設置SQL模式可讓其不刪除空格顯示: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;  # 查看錶內容,還有長度

image-20210131134600631

  • 設置SQL模式,填充空格 : SET sql_mode = 'pad_char_to_full_length';

image-20210131135027170

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;  # 再次查看變化

image-20210131140149490

超出規定字符數測試

insert into t01 values("abc 你好 aaaaaaaaaaaaaaaaaaaa");
select n,hex(n),length(n),char_length(n) from t01;

image-20210131141256136

2.varchar 類型

  • 特色 : 變長, 精準, 節省空間, 但存取速度慢
  • 字符長度範圍 : 0-65535(若是大於21845會提示用其餘類型 。mysql行最大限制爲65535字節,字符編碼爲utf-8
  • 存儲特色 :
    • varchar類型存儲數據的真實內容,不會用空格填充,若是'ab ',尾部的空格也會被存起來
    • varchar類型會在真實數據前加1-2Bytes的前綴,該前綴用來表示真實數據的bytes字節數(1-2Bytes最大表示65535個數字,正好符合mysql對row的最大字節限制,即已經足夠使用)
    • 若是真實的數據<255bytes則須要1Bytes的前綴(1Bytes=8bit 2**8最大表示的數字爲255)
    • 若是真實的數據>255bytes則須要2Bytes的前綴(2Bytes=16bit 2**16最大表示的數字爲65535)
  • 查詢 : 尾部有空格會保存下來,在查詢(檢索)時,也會正常顯示包含空格在內的內容
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;

image-20210131144007936

select x,y,length(x),length(y) from t01;  # 查看字符長度

image-20210131144427023

3.char 和 varchar 對比總結

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來講是不須要的。

六.枚舉類型與集合類型

做用 : 讓字段的值只能在給定的範圍內進行選擇 : 多選, 單選

1.枚舉類型 (enum)

  • 單選, 只能在給定範圍內選擇一個值, 好比性別, 只能從男、女、太監中選擇一個
create table t03(name varchar(10),sex enum("male","female","eunuch"));
insert t03(name,sex) values("shawn","male");  # 選擇一個性別
select sex from t03;

image-20210131152242582

  • 選擇不存在的性別測試
insert t03 values("song","wooo");  # 插入一條記錄, sex字段選擇一個不存在的選項
select * from t03;

image-20210131153012628

2.集合類型 (set)

  • 多選, 在給定範圍內能夠選擇一個或多個值, 好比愛好能夠有多種(read,run,eat,sleep,play...)
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;

image-20210131154146647

七.綜合練習

存一個員工的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());

image-20210131161231398

  • 驗證 "信息最近修改時間" 這個字段自動更新時間
update info set name="派大星" where name="xing";  # 更新一個字段
select * from info;  # 查看是否變化

image-20210131161709918

相關文章
相關標籤/搜索