?感謝您閱讀本篇文章,文章內容是個人學習筆記的整理,如果哪里有誤的話還請您指正噢?
? 個人主頁:余輝zmh–CSDN博客
? 文章所屬專欄:MySQL篇–CSDN博客
文章目錄
- 數據類型
- 1.數據類型分類
- 2.數值類型
- int整形類型
- bit位類型
- float小數類型
- 3.字符串類型
- 4日期和時間類型
- 5.enum和set
- enum類型
- set類型
數據類型
1.數據類型分類
分類 | 數據類型 | 說明 |
---|---|---|
數值類型 | BIT(M) | 位類型。M指定位數,默認值1,范圍1-64 |
TINYINT [UNSIGNED] | 帶符號的范圍-128~127 ,無符號范圍0~255 ,默認有符號 | |
BOOL | 使用0和1表示真和假 | |
SMALLINT [UNSIGNED] | 帶符號范圍-2^15~2^15-1 ,無符號范圍0~2^16-1 | |
INT [UNSIGNED] | 帶符號范圍-2<^31~2^31-1 ,無符號范圍0~2^32-1 | |
BIGINT [UNSIGNED] | 帶符號范圍-2^63~2^63-1 ,無符號范圍0~2^64-1 | |
FLOAT[(M,D)] [UNSIGNED] | M指定顯示長度,D指定小數位數,占用4字節 | |
DOUBLE[(M,D)] [UNSIGNED] | 表示比float精度更大的小數,占用空間8字節 | |
DECIMAL(M,D) [UNSIGNED] | 定點數M指定長度,D表示小數點的位數 | |
文本、二進制類型 | CHAR(size) | 固定長度字符串,最大255 |
VARCHAR(size) | 可變長度字符串,最大長度65535 | |
BLOB | 二進制數據 | |
TEXT | 大文本,不支持全文索引,不支持默認值 | |
時間日期 | DATE/DATETIME/TIMESTAMP | 日期類型(yyyy-mm-dd),(yyyy-mm-dd hh:mm:ss),timestamp時間戳 |
String類型 | ENUM類型 | 字符串對象,值來自表創建時在列規定中顯示枚舉的一個列值 |
SET類型 | 字符串對象,可包含零或多個允許值,多個值用逗號分隔(值中不能包含逗號) |
接下來會講解幾個常用類型的使用:
2.數值類型
int整形類型
1.TINYINT
TINYINT -- 有符號:-128 到 127
TINYINT UNSIGNED -- 無符號:0 到 255
- 存儲空間大小:1字節;
- 常見用途:布爾值,狀態標志,年齡等小數值;
- 示例:
create table users(id int,age tinyint,status tinyint
);
不管是有符號還是無符號的,插入的數值必須在要求范圍中才能插入成功,否則就會插入失敗
后面的幾個整型類型也是如此,就不演示了。
2.SMALLINT
SMALLINT -- 有符號:-32,768 到 32,767
SMALLINT UNSIGNED -- 無符號:0 到 65,535
- 存儲空間大小:2字節;
- 常見用途:年份,端口號,小計數值等;
3.INT
INT -- 有符號:-2,147,483,648 到 2,147,483,647
INT UNSIGNED -- 無符號:0 到 4,294,967,295
- 存儲空間大小:4字節;
- 常見用途:主鍵,用戶ID,計數器等;
4.BIGINT
BIGINT -- 有符號:-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
BIGINT UNSIGNED -- 無符號:0 到 18,446,744,073,709,551,615
- 存儲空間大小:8字節;
- 常見用途:大數值,時間戳,大數據場景等;
注意:
- 盡量不要使用
unsigned
無符號,對于int
類型存不下的數據,換成int unsigned
同樣可能存不下,那還不如直接設置成一個更大的int
類型;- 較小的整形索引更快,選擇合適的類型可以節省空間,而且整形比字符串要更加高效;
bit位類型
1.語法格式
BIT(M) -- M表示位數, 范圍1-64
2.基本用法
- 單比特存儲
create table flags(id int,is_active bit(1), -- 存儲0/1is_deleted bit(1) -- 存儲0/1
);
- 多比特存儲
create table permissions(id int,user_flag bit(8), -- 8位用戶權限system_flag bit(32) -- 32位系統標志
);
3.存儲范圍:
BIT(1) -- 0 或 1
BIT(8) -- 0 到 255
BIT(16) -- 0 到 65535
BIT(32) -- 0 到 4294967295
BIT(64) -- 0 到 18446744073709551615
4.插入數據:
-- 方式1:使用十進制
insert into permissions values(1001, 21, 252);-- 方式2:使用b前綴(b表示二進制字面量) 比較推薦這種寫法
insert into permissions values(1002, b'10101', b'11111100');-- 方式3:使用十六進制
insert into permissions values(1003, 0x15, 0xFC);
5.查詢和顯示:
-- 默認顯示
select *from permissions;
在較新版本的MySQL8.0
中,BIT類型默認以十六進制格式顯示(在老版本中會顯示看不見任何數據):
除了默認格式顯示,也可以指定形式顯示:
select id,bin(user_flag) as user_flag_binary, -- 二進制格式顯示hex(system_flag) as system_flag_hex -- 十六進制格式顯示from permissions;
float小數類型
float是單精度浮點數類型,用于存儲小數數據;
1.基本語法:
float[(M,D)] [unsigned] [zerofill]
M
:總位數(精度);D
:小數點后的位數(標度);unsigned
:無符號(非負數);zerofill
:用零填充;
存儲范圍和精度:
-- FLOAT的存儲特性
-- 范圍:-3.402823466E+38 到 -1.175494351E-38, 0, 1.175494351E-38 到 3.402823466E+38
-- 精度:約7位十進制數字
2.常用示例:
- 創建表時使用
float
:
create table products(name varchar(30),price float(8,2),weight float(8,3),rating float,discount float(3,2) unsigned
);
- 插入數據:
insert into products values('蘋果', 5.99, 0.250, 4.5, 0.10),('香蕉', 4.88, 0.200, 4.0, 0.15),('橙子', 3.99, 0.300, 3.9, 0.20);
- 查詢和計算:
-- 基本查詢
select * from products;-- 數學計算select name,price,price*(1-discount) as final_price -- 計算折扣后的價格from products;
3.精度問題
以float(4,2)為例,表示的范圍就是-99.99-99.99
,MySQL
在保存數據時會進行四舍五入;如果是float(8.2),表示的范圍就是-99999999.99-99999999.99
,同樣也是四舍五入;
insert into products values('葡萄', 2.991, 0.150, 4.1, 0.15),('桃子', 2.947, 0.350, 3.7, 0.20);
如果是一個float(4,2) unsigned 無符號的,這時表示范圍就是0-99.99
,直接把負數舍棄掉;
除了float
之外,還有一個浮點數類型decimal
,它的用法和float
一模一樣,float
怎么用,decimal
就怎么用(這里就不展示示例了),唯一的區別就是表示的精度不同;
create table test(id int,f1 float(10,8),f2 decimal(10,8)
);
對于插入相同的一個浮點數,float
和decimal
因為精度不同,導致存儲的數據不同;
float
的精度大約為7位;decimal
整數最大位數m為65位,如果m省略,默認位10;支持小數最大位數d是30,如果d被省略,默認為0;- 如果希望小數的精度高,推薦使用
decimal
;
3.字符串類型
CHAR 類型
-
固定長度:無論存儲多少字符,都占用相同的存儲空間;
-
語法:char(M) 其中 M 是字符數(1-255),char(2)表示可以存放兩個字符,可以是字母或漢字,但是不能超過2個;
-
存儲方式:總是占用 M 個字符的存儲空間,不足的部分用空格填充;
VARCHAR 類型
-
可變長度:根據實際存儲的字符數占用存儲空間;
-
語法:varchar(M) 其中 M 是最大字符數(不能超過65535字節);
-
存儲方式:只占用實際字符數 + 1-3字節的長度前綴(用來記錄數據大小);
示例:
create table student(name varchar(30),gender char(2)
);insert into student values('張三', '男'),('李四', '女');select * from student;
+--------+--------+
| name | gender |
+--------+--------+
| 張三 | 男 |
| 李四 | 女 |
+--------+--------+
注意點:
varchar(M)
中,M的大小和表的編碼密切相關;
在編碼utf8中,一個字符占用3個字節,假設長度前綴占用一個字符,就是三個字節,所以實際上有效字節數就是65535-3=65532;有效字符數就是65532/3=21844;
所以在創建表時,使用varchar
定義的字符大小一定不能超過21844,這是單個varchar
列的限制:
create table s1(name varchar(21844), -- 21844 * 3 = 65532字節
)charset utf8;
但是還要考慮整行大小限制,一行除了varchar
大小之外,還有其他字段的大小,比如下面這種情況:
create table s1(name varchar(21844), -- 21844 * 3 = 65532字節gender char(2) -- 2 * 3 = 6字節
)charset utf8;
實際計算:
-
name
列:21844字符 × 3字節 = 65532字節 -
gender
列:2字符 × 3字節 = 6字節 -
VARCHAR
長度前綴:3字節(存儲實際長度) -
總計:65532 + 6 + 3 = 65541字節 > 65535字節
正確的最大長度應該是:
-- 計算:65535 - 其他列開銷 - VARCHAR長度前綴
-- 65535 - 6 - 3 = 65526字節
-- 65526 ÷ 3 = 21842字符
char和varchar比較:
實際存儲 | char(4) | varchar(4) | char占用字節 | varchar占用字節 |
---|---|---|---|---|
abcd | abcd | abcd | 4*3=12 | 4*3+1=13 |
A | A | A | 4*3=12 | 1*3+1=4 |
Abcde | 錯 | 錯 | 數據超過長度 | 數據超過長度 |
如何選擇定長或變長字符串?
如果數據確定長度都一樣,就使用定長(char),比如:身份證,手機號,md5
如果數據長度有變化,就使用變長(varchar), 比如:名字,地址,但是你要保證最長的能存的進去。
定長的磁盤空間比較浪費,但是效率高。
變長的磁盤空間比較節省,但是效率低。
定長的意義是,直接開辟好對應的空間
變長的意義是,在不超過自定義范圍的情況下,用多少,開辟多少。
4日期和時間類型
常用的日期有以下三個:
date
:日期yyyy-mm-dd
,占用三個字節;datetime
:時間日期格式yyy-mm-dd hh:ii:ss
表示范圍從1000到9999,占用八個字節;timestap
:時間戳,從1970年開始的yyyy-mm-dd hh-ii-ss
格式和datetime
完全一致,占用四個字節;
示例:
create table birthday(-> t1 date,-> t2 datetime,-> t3 timestamp default current_timestamp-> );
default current_timestamp
:在插入數據時不用輸入,時間戳會自動補上當前時間;通常用來更新數據的插入時間;
5.enum和set
enum類型
1.基本語法
enum('值1', '值2', '值3', ...);
2.存儲機制-數字存儲
-
內部存儲:用整數存儲(1, 2, 3…),可以理解為從1開始的下標;
-
值1 = 1,值2 = 2,值3 = 3…以此類推;
-
存儲空間:1-2字節(取決于選項數量);
3.常用示例
-- 創建表
create table student (name varchar(50),gender enum('男', '女'),status enum('active', 'inactive', 'pending')
);-- 插入數據
insert into users values
('張三', '男', '1'),
('李四', '女', '2'),
('趙六', '1', '3');-- 查詢(可以用數字代替字符串)
select * from student where gender = 1; -- 等同于 where gender = '男'
select * from student where status = 2; -- 等同于 where status = 'inactive'
4.數字存儲驗證:
select gender,gender + 0 as gender_number,status,status + 0 as status_numberfrom student;
set類型
1.基本語法
set('值1', '值2', '值3', ...)
2.存儲機制-位掩碼存儲
-
內部存儲:用位掩碼(bitmask)存儲;
-
值1 = 1 (001),值2 = 2 (010),值3 = 4 (100);
-
組合存儲:多個值用位運算組合;
-
存儲空間:1-8字節(取決于選項數量);
3.位掩碼示例
-- 假設 set('A', 'B', 'C', 'D');
-- A = 1(0001)
-- B = 2(0010)
-- C = 4(0100)
-- D = 8(1000)-- 組合存儲
-- 'A, B' = 1 + 2 = 3(0011)
-- 'A, C' = 1 + 4 = 5(0101)
-- 'B, C, D' = 2 + 4 + 8 = 14(1110)
4.常用示例
-- 創建測試表create table student(name varchar(30),gender char(2),hobby set('籃球', '足球', '羽毛球', '乒乓球'));-- 插入數據
insert into student values('張三', '男', '籃球'),('李四', '女', '羽毛球, 乒乓球'),('王五', '男', '2'),('趙六', '女', '7');-- 查詢
select * from student;
select * from student where hobby = 1; -- 1對應0001,籃球
select * from student where hobby = '羽毛球'; -- 查找羽毛球的
這里就有一個問題了,在查找羽毛球時,顯示為空,但是表中明明有人包含了羽毛球,為什么會沒有顯示出來呢?
這是因為set
類型的精確匹配特性:
-
where hobby
= ‘羽毛球’ 是精確匹配; -
它只查找 hobby 字段完全等于 ‘羽毛球’ 的記錄;
-
而在上面的數據中,羽毛球都是和其他愛好組合在一起的;
但是我們實際生活中每個人都有好幾個愛好,總不能必須只有一個愛好才能查找出來吧?當然不是,這時候就要借助其他查找方式了
這里推薦兩種方式:
- 使用
find_in_set
函數:
select * from student where find_in_set('羽毛球', hobby);
- 使用位運算:
-- SET('籃球', '足球', '羽毛球', '乒乓球') 的位掩碼
-- 籃球=1, 足球=2, 羽毛球=4, 乒乓球=8
select * from student where hobby & 4;
5.位掩碼存儲驗證
select name,hobby,hobby + 0 as hobby_numberfrom student;
總結
性能優勢:
enum優勢:
存儲效率高:1-2字節 vs VARCHAR的變長存儲
查詢速度快:整數比較比字符串比較快
索引效率高:整數索引更緊湊
set優勢:
多選存儲:一個字段存儲多個值
位運算查詢:支持高效的位運算查詢
存儲緊湊:多個選項組合存儲
注意事項:
enum注意事項:
- 數字轉換:可以用數字代替字符串,但不推薦
- 修改選項:修改ENUM選項會影響現有數據
- 空值:NULL和空字符串是不同的
set注意事項:
- 順序無關:‘A,B’ 和 ‘B,A’ 等價
- 重復值:自動去重
- 位運算:理解位掩碼有助于高級查詢
位掩碼存儲驗證**
以上就是關于MySQL數據類型中常用的幾個類型的使用講解,如果哪里有錯的話,可以在評論區指正,也歡迎大家一起討論學習,如果對你的學習有幫助的話,點點贊關注支持一下吧!!!