所謂的數據類型:對數據進行統一的分類,從系統的角度出發為了能夠使用統一的方式進行管理,更好地利用有限空間。sql中將數據類型分成了3大類,分別是:數值類型、字符串類型和日期類型。
1、值類型。
數值型包括整數型和小數型。
1.1、整數型。
整數型用於存放整型數據,在Sql中因為更多地要考慮如何節省空間,系統將整型又細分為以下5類。
a)、tinyint:迷你整型。使用1個字節進行存儲,表示的狀態最多為256種(常用)。
b)、smallint:小整型。使用2個字節進行存儲,表示的狀態最多為256種(常用)。
c)、mediumint:中整型。使用3個字節存儲。
d)、int:標准整型。使用4個字節存儲(常用)。
e)、bigint:大整型。使用8個字節進行存儲。
例子練習(引出去掉符號):
創建一個名叫【my_tinyint】表,為其添加一個age字段,為其指定為數據類型為tinyint。
Create table my_tinyint(
age tinyint
)charset utf8;
插入數據:insert into my_tinyint values(255),這個時候會報錯。
錯誤原因是:超出范圍,Sql中的數值類型默認全部是有符號的,分正負,tinyint(-128到127),如果使用無符號數據,需要去掉符號,去掉符號用 unsigned,如 age tinyint unsigned,無符號從0開始。
修改字段,為字段去掉符號。
alter table my_tinyint modify age tinyint unsigned;
再次插入數據:insert into my_tinyint values(255);
指定寬度:
查看表結構的時候,發現每個字段的數據類型之后都會帶一個括號,括號里面有指定數字,里面的數字指的是寬度的意思,沒有特別的含義,只是默認第告訴用戶可以顯示的形式而已,
實際上用戶是可以控制的,這種控制不會改變數據本身的大小。
例子1:
創建一個名叫【my_tinyint1】的數據庫,為其添加一個 score 字段,數據類型為tinyint,為其指定寬度為1。
Create table my_tinyint1(
score tinyint(1) unsigned
)charset utf8;
插入數據:insert into my_tinyint1 values (255); 這個時候插入的數據是255也不會報錯(這種控制不會改變數據本身的大小)。
顯示寬度的意義在於:當數據不夠顯示寬度的時候,會自動讓數據變成對應的顯示寬度(保證數據格式)。
如果給的是2位,插入的時候插入的是1位,要顯示寬度為2位,通常需要搭配一個前導 0 來增加寬度,不改變值大小,用 zerofill 填充。零填充會導致數值自動變成無符號。
例子:創建1個名叫【my_tinyint2】的表,為其添加一個score字段,數據類型為tinyint,寬度為2,並添加 0 填充。
create table my_tinyint2(
score tinyint(2) zerofill
)charset utf8;
插入數據:insert into my_tinyint2 values(5);
1.2、小數型。
Sql中,將小數型又細分為兩種,浮點型和定點型。
1.2.1)、浮點型:
小數點浮動,精度有限,而且不會丟失精度。
浮點型數據是一種精度型數據,因為超出指定范圍之后,會丟失精度(自動四舍五入)。理論上又分為兩種精度,分別是:
a)、float:單精度。占用4個字節存儲數據,精度范圍大概為7位左右。
height float:直接使用 float 表示沒有小數部分。
money float(M,D):M 代表總長度,D代表小數部分長度。整數部分長度為 M-D。
浮點型數據的插入,整型部分是不能超出長度的,小數部分是可以超出長度(系統會自動四舍五入)。
例子:創建一張名叫【my_float1】的表,里面添加一個【money】字段,為其指定類型為float,其中整數部分為6,小數部分為5。
create table if not exists my_float1(
money float(11,5)
)charset utf8;
插入數據:
insert into my_float1 values (123456.12345); -- 小數點為5位小數(有效數據)
insert into my_float1 values (123456.123456); -- 小數點為6位小數(有效數據,小數點是可以超出指定長度,整數不可以)。
插入數據,將整數長度超過6。
insert into my_float1 values (1234567.123456); -- 小數點為6位小數(無效數據,整數部分布不能超過指定長度)。
但是有一種情況是可以超過指定長度的。浮點型一定會進行四舍五入的(超出精度范圍),浮點數如果因為系統進位導致整數部分超出指定的長度,那么系統允許成立,
如果直接插入7位整數會報錯。
insert into my_float1 values(999999.99);
1.2.2)、定點型:
小數點固定,精度固定,不會丟失精度。用 decimal 數據類型定義。
定點型會絕對的保證整數部分不會被四舍五入(不會丟失精度),小數部分有可能(理論小數部分也不會丟失精度,在自己的范圍內不會進位,不在自己范圍內會進位)。
插入數據時,定點數的整數部分一定不能超出長度(進位)不可以,小數部分的長度是可以隨意超出指定長度的(系統會自動四舍五入)。
例子:創建1個名叫【my_decimal】的表,添加一個【money】字段,為其指定數據類型為decimal,且整數長度和小數長度都為5。
create table if not exists my_decimal(
money decimal(10,5)
)charset utf8;
插入數據:
insert into my_decimal values(66666.99999); -- 整數部分不會進位(有效數據)
直接插入長度大於5的數據會報錯。
insert into my_decimal values(666666.99999); -- 整數部分不會進位(無效數據)。
那什么時候定點型數據,什么時候用浮點型數據呢?
如果數據非常精確,用定點,粗略大致算的時候就用浮點就行了。
2、字符串類型。
在Sql中,字符串類型分為6類,分別是:char、varchar、text、blob、enum和set。
a)、定長字符串 char。
char:磁盤(二維表)在定義結構的時候,就已經確定了最終數據的存儲長度。
char(L):L代length(長度)的意思,單位為字符,最大長度值為255。
char(4):在utf8環境下,需要 4 * 3 = 12個字節。
b)、變長字符串 varchar。
varchar 在分配空間的時候,按照最大的空間分配,但是實際上用了多少,是根據具體的情況來確定的。
varchar(L):L表示length(長度),理論長度是65536個字符,但是會多出 1 到 2 個字節來確定存儲的實際長度,但是實際上如果長度超過255,既不用定長,也不用變長,使用文本字符串text。
varchar(10) :存了10個漢字,在utf8環境下,需要 (10 * 3) + 1 = 31(bytes)來存儲。
定長與變長的實際存儲空間(utf8環境下)
如何選擇定長與變長的字符串呢?
定長的磁盤空間比較浪費,但是效率高,如果數據確定長度都一樣,就會使用定長,如身份證號碼、電話號碼和手機號碼。
變長的磁盤空間比較節省,但是效率低,如果數據不能確定長度(不同數據有變化),如姓名(有的人姓名為2個字,有的4個),家庭地址。
c)、文本字符串。
如果數據量非常大,通常說超過255個字符就會使用字符串。
文本字符串根據存儲的數據格式進行分類,text和blob。
text:存儲文字(二進制實際上都是存儲路徑)。
blob:存儲二進制數據(通常不用)。
d)、枚舉字符串。
枚舉:enum,事先將所有可能出現的結果都設計好,實際存儲的數據必須是定義好的數據中的其中一個。
枚舉的作用:
規范數據格式,數據只能是規定的數據的其中之一。
節省存儲空間(枚舉通常有1個別名,單選框),枚舉實際存儲的是字符串本身。
語法: enum(可能出現的元素列表)。如 enum('男','女');
例子:創建一張【my_enum】表,添加一個 sex 字段,為其指定數據類型為enum。
create table if not exists my_enum(
sex enum('男','女','保密')
)charset utf8;
插入數據:insert into my_enum values('男');
在MySql中,系統也是自動轉換數據格式的,而且基本與PHP一樣(尤其是字符串轉數字),證明字段存儲的數據是數值,將數據取出來+0,就可以判斷出原來的數據存的是字符串還是數值,如果是字符串,
最終結果永遠是0,否則就是其他值,如select sex + 0 from my_enum;
編號是從 1 開始。
枚舉原理:枚舉在進行數據規范的時候(定義的時候),系統會自動建立一個與數字與枚舉元素的對應關系(關系放到日志中),然后進行數據插入的時候,系統會自動將字符串轉換成對應的數字存儲,然后進行
數據提取的時候,系統自動將值轉換成對應的字符串顯示,如國家、省份。
枚舉可以直接插入數值(再次證明存儲的是數值)。
insert into my_enum values(1);
d)、集合字符串。
集合和枚舉很類似,實際存儲的是數值,而不是字符集(集合是多選)。
語法: 字段名 set(元素列表)
例子:創建1個名叫【my_set】的表,為其加入一個hobby字段,為其設置數據類型為集合。
create table my_set(
hobby set('足球','籃球','乒乓球')
)charset utf8;
插入數據:直接插入數值。
insert into my_set values(1);
insert into my_set values(3); 這個地方記住一下插入的3是足球籃球。
3、MySql記錄長度。
MySql中規定,任何一條記錄最長不能超過65535個字節(varchar永遠達不到理論值)。
Varchar的實際長度能達到多少呢?
utf8環境下(3個字節存一個漢字),varchar的實際頂配為21844個字符。
gbk環境下(2個字節存1個漢字),varchar的實際頂配為32766字符。
測試1、utf8環境下。
創建1個【my_utf8】表,里面添加一個【name】字段,為【name】字段設置數據類型為varchar,指定寬度為65535個字節。
create table my_utf8(
name varchar(65535)
)charset utf8;
由於上圖說,最大值只能是21845個字符,因此指定為65535報錯,那么久設置最大值為21845個字符。
create table my_utf8(
name varchar(21845)
)charset utf8;
仍然是創建失敗,那么接下來就分析一下。
(21845 * 3) + 2 = 65535 + 2 = 65537(bytes) -- 21845是最大值,utf8下是一個漢字占3個字節,+2(varchar要比實際空間多出1到2個字符出來)
因此最大只能是21844個字符,(21844 * 3) + 2 = 65532 + 2 = 65534(bytes)。
create table my_utf8(
name varchar(21844)
)charset utf8;
測試2、gbk環境下。
創建1個【my_utf8】表,里面添加一個【name】字段,為【name】字段設置數據類型為varchar,指定寬度為65535個字節。
create table my_gbk(
name varchar(65535)
)charset gbk;
由於上圖說,最大值只能是21845個字符,因此指定為65535報錯,那么久設置最大值為21845個字符。
create table my_gbk(
name varchar(32767)
)charset gbk;
仍然創建失敗,接下來分析一下。
(32767 * 2 ) + 2 = 65534 + 2 = 65536(bytes) -- 超過最大字節范圍。
因此最大只能為32766,(32766 * 2) + 2 = 65532 + 2 = 65534(bytes)
如果想要用完整個65535個字節長度。
如果想要使用完65535個字節,只需要再增加1個字段,為其指定類型為tinyint即可。
例子:
create table if not exists my_utf82(
age tinyint(1) unsigned,
name varchar(21844)
)charset utf8;
創建失敗,失敗原因:在mysql中,如果有1個字段允許為空,那么系統會自動從整個記錄中保留1個字節來存儲null(占用1個字節),若想要釋放null所占用的字節,就必須保證所有的字段不允許為空。
create table if not exists my_utf82(
age tinyint(1) unsigned not null,
name varchar(21844) not null
)charset utf8;
End。