一、數據類型分類
二、數值類型
1.bit類型
測試環境ubuntu
基本語法:
bit[(M)]:位字段類型,M表示每個值的位數,范圍從1~64;如果M被忽略,默認為1
舉例:
create table testBit(id int, a bit(8));
insert into testBit values(10,10);
select * from testBit;#當我們進行查詢的時候,發現以16進制出現
當我們以十六進制進行輸出時,發現是字符A(16進制數,還是十進制中的10)
如果我們添加一個不在范圍內的數據,如下圖所示,mysql直接拒絕了用戶的操作
如果我們向mysql特定的類型中插入不合法的數據,MySQL一般都是直接攔截我們,不讓我們做對應的操作
反過來,如果我們已經有數據被成功插入到mysql中了,一定插入的時候是合法的
所以,mysql中,一般而言,數據類型本身也是一種:約束
這種約束:倒逼程序員,讓程序員盡可能進行正確的插入
約束:約束使用者
另外,如果你不是一個很好的使用者,mysql也能保證數據插入的合法性;這樣就能夠保證數據庫中的數據是可預期的,完整的
測試環境Centos
bit使用注意事項:
2.tinyint類型
語法:
tinyint [unsigned]
【測試一】有符號tinyint測試(-128~127):
create table testTinyInt(num tinyint);
insert into testTinyInt values(127);
insert into testTinyInt values(-128);
insert into testTinyInt values(0);
desc testTinyInt;
現在插入越界數值,mysql會拒絕插入
insert into testTinyInt values(128);
insert into testTinyInt values(-129);
【測試二】無符號tinyint測試(0~255)
create table testTinyIntUn(num tinyint unsigned);
insert into testTinyIntUn values (0);
insert into testTinyIntUn values (255);
insert into testTinyIntUn values (128);
select * from testTinyIntUn;
desc testTinyIntUn;
現在插入越界數值,mysql會拒絕插入
insert into testTinyIntUn values(-1);
insert into testTinyIntUn values(-256);
說明:
- 在MySQL中,整型可以指定是有符號的和無符號的,默認是有符號的
- 可以通過unsigned來說明某個字段是無符號的
- 根據自己實際情況選擇不同類型,雖然不同類型之間只差幾個字節,但是用于百萬級別,千萬級別列表情況下,省下來的不是一芯半點了
3.int類型
語法:
int(M) zerofill
M
:這是可選的參數,用于指定顯示寬度。M
的值指定了該字段顯示的最小位數。如果插入的數值的位數少于M
指定的位數,那么數值將在左側填充零以達到指定的寬度。ZEROFILL
:這是一個屬性,當與INT
類型一起使用時,如果數值的位數少于指定的寬度,則在數值的左側填充零。
需要注意的是:
ZEROFILL
不會改變數值的實際存儲大小。即使指定了INT(5) ZEROFILL
,整數仍然是按照INT
的標準大小(通常是4字節)存儲的。- 如果數值超過了
M
指定的位數,那么ZEROFILL
不會起作用,數值將按原樣顯示,而不會填充零。 ZEROFILL
自動為該字段添加UNSIGNED
屬性,這意味著你不能在該字段中存儲負數。
4.float類型
float[(m,d)] [unsigned]:m指定顯示長度,d指定小數位置,占用空間4個字節;那么整數部分位數為m-d
【示例一】設計一個表,該表表示的范圍是 -99.99~99.99,MySQL在保存值時會進行四舍五入
create table testFloat(id int, salary float(4,2));
insert into testFloat values(1, -99.99);
insert into testFloat values(2, -99.991);#多的這一點被拿掉了
insert into testFloat values(3, 3);
insert into testFloat values(4, 0.1);
只要在當前字段范圍內的數值,若該數值的小數位數不滿d為,mysql會自動在后面補0
float類型會進行四舍五入,如果五入后超出表示范圍,則會報錯
insert into testFloat values(5, 99.995);
【示例二】如果定義的是float(4,2) unsigned ,因為把它指定為無符號的數,范圍是0~99.99
create table testFloatUn(id int, salary float(4,2) unsigned);
insert into testFloatUn values(100, -0.1);
注意:在MySQL中,使用 FLOAT
或 DOUBLE
數據類型時可能會遇到精度丟失的問題。這是因為 FLOAT
和 DOUBLE
類型是基于IEEE標準的浮點數,它們在內部使用二進制格式來表示數值,這可能導致某些十進制小數不能精確表示。
create table testFloatDe(num float);
insert into testFloatDe values(123456789.987654321);
select * from testFloatDe;
MySQL中的 FLOAT
類型默認精度通常是單精度(32位),它只能保證大約7到8位十進制數的精度。當你插入一個非常大的數值,或者一個包含非常多小數位的數值時,超出這個精度的部分就會被舍入或者直接丟失,為了避免精度丟失,我們使用decimal類型
5.decimal類型
語法:
decimal[(m,d)] [unsigned] # 定點數m指定長度,d表示小數點的位數
- decimal(5,2) 表示的范圍是 -999.99 ~ 999.99
- decimal(5,2) unsigned 表示的范圍 0 ~ 999.99
- decimal 和 float 很像,但是有區別:float 和 decimal 表示的精度不一樣
create table testDecimal(id int, salary float(10,8), salary2 decimal(10,8));
insert into testDecimal values(1,12.34567890, 12.34567890);
發現decimal的精度更準確,因此如果我們希望某個數據表示高精度,選擇decimal
decimal整數最大位數m為65,支持小數最大位數d是30.如果d被省略,默認為0。如果m被省略默認是10
三、文本、二進制類型
1.char類型
語法:
char(L) #固定長度字符串,L是可以存儲的長度,單位為字符,最大長度值可以為255
create table testChar(name char(20));
insert into testChar values('zhangsan');
insert into testChar values('張三');
無論是漢字還是字符,在mysql中都認為是一個字符
在utf_8中,一個漢字是3個字節;gbk下一個漢字2個字節
char(2)表示可以存放兩個字符,可以是字母或者漢字,但是不能超過2個,最多只能是255
create table testChar1(name char(2));
insert into testChar1 values('張三');
create table testChar2(name char(256));
2.varchar類型
語法:
varchar(L) #可變長度字符串,L表示字符長度,最大長度65535個字節
舉例:
create table testVarchar(id int, name varchar(20));
insert into testVarchar values(1,'張三');
insert into testVarchar values(2,'lisi');
說明:關于varchar(len),len到底是多大,這個len值,和表的編碼密切相關
- varchar長度可以指定為0到65535之間的值,但是有1到3個字節用于記錄數據大小,所以說有效字節數是65532。
- 當我們的表的編碼是utf8時,varchar(n)的參數n最大值是65532/3=21844[因為utf中,一個字符占用3個字節],如果編碼是gbk,varchar(n)的參數n最大是65532/2=32766(因為gbk中,一個字符占用2字節)。
2.1.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), 比如:名字,地址,但是你要保證最長的能存的進去。
- 定長的磁盤空間比較浪費,但是效率高。
- 變長的磁盤空間比較節省,但是效率低。
- 定長的意義是,直接開辟好對應的空間
- 變長的意義是,在不超過自定義范圍的情況下,用多少,開辟多少。
3.日期和時間類型
常用的日期類型有3中,分別如下:
- date:日期
yyyy-mm-dd
,占用三個字節 - datetime:時間日期
yyyy-mm-dd hh:mm:ss
,占用八個字節 - timestamp:時間戳,從1970年開始經過的秒數,表示格式與datetime一致
yyyy-mm-dd hh:mm:ss
,占用四個字節
案例:
# 創建表
create table birthday(t1 date, t2 datetime, t3 timestamp);# 插入數據 插入兩種時間
insert into birthday(t1,t2) values('2001-1-1','2022-6-7 19:00:00');select * from birthday;
ubuntu環境下,添加數據時,時間戳不會自動補上當前時間
centos環境下,添加數據時,時間戳會自動補上當前時間
centos環境下,更新數據時,時間戳會更新當前時間
//創建表
mysql> create table birthday(t1 date, t2 datetime, t3 timestamp);
Query OK, 0 rows affected (0.01 sec)//插入數據:
mysql> insert into birthday(t1,t2) values('1997-7-1','2008-8-8 12:11:1'); -- 插入兩種時間
Query OK, 1 row affected (0.00 sec)mysql> select * from birthday;
+------------+---------------------+---------------------+
| t1 | t2 | t3 |
+------------+---------------------+---------------------+
| 1997-07-01 | 2008-08-08 12:01:01 | 2024-11-10 21:22:55 | --添加數據時,時間戳自動補上當前時間
+------------+---------------------+---------------------+//更新數據:
mysql> update birthday set t1='2000-1-1';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0mysql> select * from birthday;
+------------+---------------------+---------------------+
| t1 | t2 | t3 |
+------------+---------------------+---------------------+
| 2000-01-01 | 2008-08-08 12:01:01 | 2024-11-10 21:23:09 | -- 更新數據,時間戳會更新成當前時間
+------------+---------------------+---------------------+
四、String類型
1.enum
基本語法:
enum('可選選項1','可選選項2','可選選項3',...)
enum:枚舉,“單選”類型;
該設定只是提供了若干個選項的值,最終一個單元格中,實際只存儲了其中一個值;而且出于效率考慮,這些值實際存儲的是“數字”,因為這些選項的每個選項值依次對應如下數字:1,2,3,…最多65535個;當我們添加枚舉值時,也可以添加對應的數字編號
enum比如可以用在性別字段中,只能選擇男女
create table student (name varchar(20), gender enum('男','女'));
insert into student values('張三','男');
insert into student values('李四','女');
如果選擇enum之外的值,會報錯
insert into student values('王五','保密');
這里的enum類似于C/C++中的enum,第一個選項代表1,第二個代表選項代表2
單選選項對應的數字是從1開始編號的,而不是從0開始編號的,超出enum的選項值會報錯
insert into student values('趙六','1');
insert into student values('田七','2');
2.set類型
set:集合,“多選”類型
基本語法:
set('可選選項1','可選選項2','可選選項3',...)
該設定只是提供了若干個選項的值,最終一個單元格中,設計可存儲了其中任意多個值。最多可以設置64個選項。
【案例】:有一個調查表votes,需要調查人的喜好,比如(登山,游泳,籃球,武術)中去選擇(可以多選),(男,女)[單選]
create table votes(name varchar(20),gender enum('男','女'),# 注意:使用數字標識的時候,就是正常的從1開始的數組下標hobby set('登山','游泳','籃球','武術') #注意:使用數字標識每個愛好的時候,想想Linux權限,采用比特位位置來和set中愛好對應起來
);
插入數據
insert into votes values('張三','男','登山,武術');
insert into votes values('李四','2','登山,武術');
select * from votes where gender=2;
有如下數據,想查找所有喜歡籃球的人:
使用如下查詢語句
select * from votes where hobby="籃球";
不能查詢出所有愛好為籃球的人
集合查詢使用 find_in_set 函數
find_in_set(sub,str_list)
:如果 sub 在 str_list 中,則返回下標;如果不在,返回0;str_list是用逗號分隔的字符串。
喜好為籃球的人
select * from votes where find_in_set('籃球',hobby);
不建議在enum中使用選項對應的枚舉值,集合值的時候采用數字的方式,因為不利于閱讀。
set補充
set使用位圖的方式存儲各個選項,第一個選項對應1(20),第二個選項為2(21),第三個選項為4(2 ^ 2);這樣存儲可以大大提高存儲效率
登山:000001---->1
游泳:000010 —>2
登山+游泳:000011 —>3