MySQL快速入門04----數據類型

一 MySQL數據類型分類



由上圖可以看到,MySQL的數據類型可以分爲三大類:數值型,時間日期型和字符創型,接下來我們分別講解這三種類型。

二 數值型


2.1 整數型



整數類型可以分爲以下幾種:

  • 可使用unsigned控制是否有正負
  • 可以使用zerofill來進行前導零填充
  • 也存在 布爾bool類型,但是就是tinyint(1)的別名


整數
  • TINYINT[(M)] [UNSIGNED] [ZEROFILL]
  • SMALLINT[(M)] [UNSIGNED] [ZEROFILL]
  • MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL]
  • INT[(M)] [UNSIGNED] [ZEROFILL] 也可以使用 INTEGER
  • BIGINT[(M)] [UNSIGNED] [ZEROFILL]
其中M,表示顯示寬度,顯示寬度不限制數值的範圍。配合zerofill來使用,可以在小於顯示寬度的位數前增加0.zerofill自動爲unsigned,其中unsigned 表示無符號,只表示正數。

2.1.1 無格式控制


創建一個表,表中有兩種類型的數據,一種爲tinyint型,另外一種爲int型數據,都是有符號類型且無填充的。
mysql> create table if not exists int_1(
    -> `numA` tinyint,
    -> `numB` int
    -> );
Query OK, 0 rows affected (0.05 sec)

向該表中插入數據
mysql> insert into int_1 values(100, 101);
mysql> insert into int_1 values(1, 12);
mysql> insert into int_1 values(-1, 12);

數據展示:
mysql> select * from int_1;
+------+------+
| numA | numB |
+------+------+
|  100 |  101 |
|    1 |   12 |
|   -1 |   12 |
+------+------+
3 rows in set (0.00 sec)
從展示的數據可以看出,默認的行爲是有符號類型的,沒有填充的類型。

對於有符號類型,tinyint佔用一個字節,取值範圍爲-128~127;而int佔用四個字節,取值範圍爲-32768~32767;

mysql> insert into int_1 values(127, 12);
Query OK, 1 row affected (0.03 sec)

mysql> insert into int_1 values(128, 12);
ERROR 1264 (22003): Out of range value for column 'numA' at row 1
mysql> insert into int_1 values(-128, 12);
Query OK, 1 row affected (0.02 sec)

mysql> insert into int_1 values(-129, 12);
ERROR 1264 (22003): Out of range value for column 'numA' at row 1
從上述內容可以看到,MySQL對於插入超出範圍的數的處理方式時報錯!不會像CPP語言一樣溢出!!!

2.1.2 有格式控制


創建表int_2,控制顯示數字的最小寬度爲3,無符號類型,用前導零來填充;
mysql> create table if not exists int_2(
    -> `numA` tinyint(3) unsigned zerofill,
    -> `numB` int(3) unsigned zerofill
    -> );
Query OK, 0 rows affected (0.06 sec)

插入數據
mysql> insert into int_2 values(1, 1);
mysql> insert into int_2 values(12, 1234);

數據展示:
mysql> select * from int_2;
+------+------+
| numA | numB |
+------+------+
|  001 |  001 |
|  012 | 1234 |
+------+------+
2 rows in set (0.00 sec)
從數據展示中我們可以看出,通過規定數據的顯示寬度可以達到統一顯示的目的,類型(M)表示的顯示的最小寬度是多少,不會影響寬度大於M的數字。
而想要實現這種自定義顯示寬度的效果,就需要前導零填充,我們稱之爲zerofill。

注意:
  • 設置寬度顯示不影響數的取值範圍,數的取值範圍是有數據類型決定的;
  • 設置顯示寬度不會發生數據截取的現象。


2.2 小數型



  • 小數型可以用(M,D)控制數值的範圍;
  • 可以是無符號的;
  • 可以zerofill;
  • 可以使用無符號數


單精度:FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

雙精度:DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]
其中M表示總的位數,D表示小數位數。此M,D可以控制保存的範圍。Float(10,2) -99999999.99 到 99999999.99
如果省略M,D會根據計算機硬件進行處理單精度,M大約爲7左右;而雙精度,M大約爲15左右。

定點數:DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]
其中M表示總的位數,D表示小數位數。此M,D可以控制保存的範圍。
M,D省略,默認爲10,0

注意:可以unsigned 但是不會影響範圍。


2.2.1 float類型和double類型



NO1 創建一個沒有空格控制的float表
mysql> create table if not exists float_1(
    -> `fl` float,
    -> `f2` double
    -> );
Query OK, 0 rows affected (0.06 sec)
創建一個沒有格式控制的表,表中有兩種數據類型,一種爲float類型,另外一種爲double類型,都是有符號類型,沒有填充的;

向該表中插入數據:
mysql> insert into float_1 values(12.123, 1234.5678);
mysql> insert into float_1 values(-12.123, -1234.5678);

數據展示:
mysql> select * from float_1;
+---------+------------+
| fl      | f2         |
+---------+------------+
|  12.123 |  1234.5678 |
| -12.123 | -1234.5678 |
+---------+------------+
2 rows in set (0.00 sec)

控制數值的範圍(和整型不同),type(M,D)表示小數位數最多爲三位,整數部分最多爲M-D位,超過這麼多位的情況下會提示插入數據錯誤,當然了,如果插入的數據超過了數據的取值範圍的話也會發生錯誤。(M表示所有的數值位數,不包含小數點和符號;D表示允許的小數位數)。


創建一個擁有格式控制的float表
mysql> create table if not exists float_2(
    -> `f1` float(5,2) zerofill,
    -> `f2` double(6,3) zerofill
    -> );
Query OK, 0 rows affected (0.06 sec)
上方的表中f1中可以有五位數,小數點佔兩位、整數佔三位,當填充的數字不足時用前導零來填充
上方的表中f2中可以有六位數,小數點佔三位、整數佔三位,當填充的數字不足時用前導零來填充

向裏邊插入數據:
mysql> insert into float_2 values(12.34, 12.34);
mysql> insert into float_2 values(1.1, 1.2);
mysql> insert into float_2 values(123.45, 123.456);

數據展示:
mysql> select * from float_2;
+--------+---------+
| f1     | f2      |
+--------+---------+
|  12.34 |  12.340 |
|  01.10 |  01.200 |
| 123.45 | 123.456 |
+--------+---------+
3 rows in set (0.00 sec)

注意:當插入數據的位數超過規定的額定值以後,插入出錯!
mysql> insert into float_2 values(123456.1, 123456.34);
ERROR 1264 (22003): Out of range value for column 'f1' at row 1
mysql> insert into float_2 values(1234.12, 123456.34);
ERROR 1264 (22003): Out of range value for column 'f1' at row 1

NO2 浮點數的科學計數發(E)

浮點數支持科學計數法,如插入數據時:
mysql> insert into float_2 values(0.1234E2, 0.123456E3);
Query OK, 1 row affected (0.02 sec)

數據展示:
mysql> select * from float_2;
+--------+---------+
| f1     | f2      |
+--------+---------+
|  12.34 |  12.340 |
|  01.10 |  01.200 |
| 123.45 | 123.456 |
|  12.34 | 123.456 |
+--------+---------+
4 rows in set (0.00 sec)

當向表中插入的小數點位數多餘分配的位數的時候,小數點會四捨五入!
mysql> insert into float_2 values(12.126, 12.34);
Query OK, 1 row affected (0.02 sec)

數據展示:
|  12.13 |  12.340 |
+--------+---------+




2.2.2 定點數


定點數應對精度要求特別高的情況,由自己設定,不會出現字符串丟失的情況。
decimal(M,D),其中M表示總的位數,D表示小數位數。

注意:
  • 小數超過位數的話會出現四捨五入的情況,不會報錯;
  • 默認情況下,M爲10,D爲0;


創建一個定點數表:
mysql> create table if not exists float_3(
    -> `f` decimal(10,4) unsigned zerofill
    -> );
Query OK, 0 rows affected (0.07 sec)

插入數據:
mysql> insert into float_3 values(123.45);
mysql> insert into float_3 values(123.4567);
mysql> insert into float_3 values(123.45678);

數據展示:
mysql> select * from float_3;
+-------------+
| f           |
+-------------+
| 000123.4500 |
| 000123.4567 |
| 000123.4568 |
+-------------+
3 rows in set (0.00 sec)

2.3 時間日期


DATETIME,TIMESTAMP,DATE,在保存數據時,針對數據格式與合法性進行驗證,不對日期時間的合法性進行驗證。
年月日時分秒的分隔符可以是任意的標點,但是常用的是-和:,甚至是不使用都可以。
2位的年也是被允許的,但是表示的範圍70-69 表示:1970-2069範圍

TIMESTAMP:時間戳,年份是一個範圍

TIME:TIME類型不僅可以用於表示一天的時間,還可以表示一個間隔時間(或者過去了多久)
因此該類型可以設置爲多個小時,甚至是 幾天幾小時幾分鐘幾秒的情況 D HH:II:SS。
同樣在設置時分秒時,可以使用其他標點符號作爲分隔符,甚至是不用(用天了就不行了)。

2.3.1 Datetime(年月日時分秒)


範圍是:支持任意分隔符的日期,也可以不加分隔符,也就是說只要有分隔符即可!但是日期範圍必須要正確,如月份不能超過12

創建一個時間表date_1:
mysql> create table if not exists date_1(
    -> myDate datetime
    -> );
Query OK, 0 rows affected (0.05 sec)

向時間表中插入數據:
mysql> insert into date_1 values('20160803142011');
Query OK, 1 row affected (0.02 sec)

mysql> insert into date_1 values(20160803142015);
Query OK, 1 row affected (0.01 sec)

mysql> insert into date_1 values('2016-08-03 14:20:25');
Query OK, 1 row affected (0.02 sec)

數據展示:
mysql> select * from date_1;
+---------------------+
| myDate              |
+---------------------+
| 2016-08-03 14:20:11 |
| 2016-08-03 14:20:15 |
| 2016-08-03 14:20:25 |
+---------------------+
3 rows in set (0.00 sec)
從上方我麼可以看到,插入的時間必須要在一定的範圍之內,插入時間的格式多種多樣,既可以是字符串(用單引號引起來),也可以是單純的整數,同時也可以使用分隔符(使用分隔符的時候相當於使用字符串,一定要用單引號引起來);

注意:
  • 插入的時間一定要在其允許的範圍之內;
  • 分隔符可以是任意的字符,但是爲了方便起見,在年份中一般用‘-’,在時間中一般用‘:’。

時間值是可以有零值的,插入零值:
mysql> insert into date_1 values(0);

零值展示:
| 0000-00-00 00:00:00 |

插入的數據也可以是不完全的,例如:
mysql> insert into date_1 values('16:08:03');
Query OK, 1 row affected (0.03 sec)

數據展示(默認插入的爲年月日,其實就是從前往後進行推算):
| 2016-08-03 00:00:00 |

2.3.2 時間戳timestamp(年月日時分秒/整數)


存儲時用整數、字符串都可以,表示日期和時間;

範圍是:支持任意分隔符的日期,也可以不加分隔符,也就是說只要有分隔符即可!但是日期範圍必須要正確,如月份不能超過12。

創建時間戳表date_2:
mysql> create table if not exists date_2(
    -> `t` timestamp
    -> );
Query OK, 0 rows affected (0.14 sec)

向時間戳表date_2中插入數據:
mysql> insert into date_2 values(20160803143415);
Query OK, 1 row affected (0.02 sec)

mysql> insert into date_2 values('20160803143420');
Query OK, 1 row affected (0.02 sec)
mysql> insert into date_2 values('2016-08-03 14:34:25');
Query OK, 1 row affected (0.02 sec)

數據展示:
mysql> select * from date_2;
+---------------------+
| t                   |
+---------------------+
| 2016-08-03 14:34:15 |
| 2016-08-03 14:34:20 |
| 2016-08-03 14:34:25 |
+---------------------+
3 rows in set (0.00 sec)
從上方代碼可以看到,時間戳和方法和datetime是一致的,這裏不再詳細贅述!

與datetime不同的一點是:檢索列時,+0 可以檢索時間戳,其實是一個整數的形式(去掉了連接符號)
其次就是表示的範圍不一樣,這是由所佔用的字節數決定的。
mysql> select t+0 from date_2;
+----------------+
| t+0            |
+----------------+
| 20160803143415 |
| 20160803143420 |
| 20160803143425 |
+----------------+
3 rows in set (0.00 sec)


2.3.3 date(年月日)

創建日期表date_3:
mysql> create table if not exists date_3(
    -> `t` date
    -> );
Query OK, 0 rows affected (0.05 sec)

插入數據:
mysql> insert into date_3 values(20160803);
Query OK, 1 row affected (0.03 sec)

mysql> insert into date_3 values('20160803');
Query OK, 1 row affected (0.03 sec)

mysql> insert into date_3 values('2016:08:03');
Query OK, 1 row affected (0.02 sec)

數據展示:
mysql> select * from date_3;
+------------+
| t          |
+------------+
| 2016-08-03 |
| 2016-08-03 |
| 2016-08-03 |
+------------+
3 rows in set (0.00 sec)

其實上述三種時間數據類型還支持2爲年份的插入方式(不建議使用):
mysql> insert into date_3 values('16:08:03');
Query OK, 1 row affected (0.03 sec)
mysql> insert into date_3 values('80:08:03');
Query OK, 1 row affected (0.03 sec)

數據展示:
| 2016-08-03 |
| 1980-08-03 |


70-69 1970 - 2069
70-99 19xx(默認)
0-69 20xx年(默認)

語法上沒有錯誤,但是不建議使用!

2.3.4 time(時間)


表示的意義:
1,一天中的時間
2,表示時間間隔,在表示間隔時(也就是過去了多長時間),
可以使用天來表示。格式:
D HH:MM:SS
D表示天(最大爲34)

創建時間表date_4:
mysql> create table if not exists date_4(
    -> `t` time
    -> );
Query OK, 0 rows affected (0.07 sec)

插入數值:
mysql> insert into date_4 values('14:55:27');
Query OK, 1 row affected (0.03 sec)

mysql> insert into date_4 values('5 14:55:27');
Query OK, 1 row affected (0.02 sec)

數據展示:
mysql> select * from date_4;
+-----------+
| t         |
+-----------+
| 14:55:27  |
| 134:55:27 |
+-----------+
2 rows in set (0.00 sec)
第一條表示插入的時間數值;
第二條表示已經過去了多長時間。

2.3.5 year(年)


由於year只佔用一個字節,只能表示1901-2155的取值範圍。

創建一個year表date_5:
mysql> create table if not exists date_5(
    -> `y` year
    -> );
Query OK, 0 rows affected (0.09 sec)

插入1234,這時候會提示數據越界:
mysql> insert into date_5 values(1234);
ERROR 1264 (22003): Out of range value for column 'y' at row 1

插入正常範圍內的數據:
mysql> insert into date_5 values(1999);
Query OK, 1 row affected (0.02 sec)

mysql> insert into date_5 values(2016);
Query OK, 1 row affected (0.02 sec)

數據展示:
mysql> select * from date_5;
+------+
| y    |
+------+
| 1999 |
| 2016 |
+------+
2 rows in set (0.00 sec)

2.4 字符串類型




Char & varchar
CHAR和VARCHAR類型聲明的長度表示你想要保存的最大字符數。

Char,定長字符串,保存時如果字符串長度不夠,則後邊補足空字符串;但是在讀取到數據是,會截取後邊所有的字符串。因此如果真實數據存在左邊空格,則需要注意。
varchar,變長字符串。在保存字符串時,同時保存該字符串的長度,小於255採用一個字節保存,否則採用二個字節保存。不會像char一樣截取空格。

在定義類型長度時,同時一條記錄的總長度是 65535.因此所有字段的總長度不能超過改值。同時每條記錄還需要一個字節保存是否有null值,如果都沒有null(都不允許爲null)則該字節省略。

枚舉
ENUM('value1','value2',...)
枚舉值應該在值列表內,允許使用下標方式標識。1標識第一個元素,逐個遞增。
除此之外,允許null和空字符串(下標爲0)
下標方式,可以使用在檢索中。

集合
Set(‘value1’,’value2’,…);
表示可以選擇可用值的0個或多個組合。

二進制類型:
如果需要保存一個二進制文件內容的話,應該保存成這些類型,例如圖片內容。

2.4.1 char & varchar類型


char(M)表示固定長度;
varchar(M)表示可變長度。
其中M表示允許的字符串的長度,M在varchar中的表示,是允許的最大長度;char內M表示嚴格限定的長度。
  char(5) varchar(5)                        
‘’        5個字符                       1個字符                                  varchar需要一個字節保存字符串總長度
‘abc’                 5 4  
‘abcde’   5 6  
       

M表示的是字符數,而不是字節數。但是,總的長度的使用是按照 字節計算的。

存儲格式取決於當前數據庫的字符集:
utf8中一個字符佔用三個字節21845*3 = 65536
gbk中一個字符佔用兩個字節32767*2 = 65534

常見一個最大長度字符表str_1:
mysql> create table if not exists str_1(
    -> `c` char(255)
    -> );
Query OK, 0 rows affected (0.07 sec)

創建一個最大(65535)的varchar數據類型表(失敗):
mysql> create table if not exists str2(
    -> `c` varchar(65535)
    -> )character set latin1;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to cha
ge some columns to TEXT or BLOBs
mysql>
因爲varchar類型除了還要保存額外總的字符個數,除了類型本身的限制之外,還有記錄總的長度;

創建成功的最大實例(字符集latin1只佔用一個字符):
mysql> create table if not exists str2(
    -> `c` varchar(65533) not null
    -> )character set latin1;
Query OK, 0 rows affected (0.09 sec)

創建不成功(超過255個字符,就要用兩個字節保存字符個數,且null也佔用一個字符):
mysql> create table if not exists str3(
    -> `c` varchar(65533)
    -> )character set latin1;
ERROR 1118 (42000): Row size too large. The m
ge some columns to TEXT or BLOBs
mysql>

創建成功:
mysql> create table if not exists str3(
    -> `c` varchar(65532)
    -> )character set latin1;
Query OK, 0 rows affected (0.09 sec)


真是的varchar長度:
記錄存在總長度 65535限制。
varchar特點,當 類型數據超過255個字符時,採用2個字節表示長度。
65535-2=65533
整條記錄,需要一個額外的字節,用於保存當前字段的null值。
除非所有的字段都比不是nul,這個字節纔可以省略。一個記錄,不論有多少個字段
存在null,都是使用統一的一個字節來表示。而不是每個字段一個字節。

創建不成功,因爲下邊的tinyint也要佔用一個null字節:
mysql> create table if not exists str4(
    -> `c` varchar(65533) not null,
    -> `i` tinyint
    -> )character set latin1;
ERROR 1118 (42000): Row size too large. The maximum
ge some columns to TEXT or BLOBs

2.4.2 test


能保存的長度2^16,總長度2^16+2,需要額外的兩個字節
文本,有很多 兄弟類型(不用指定長度)Tinytext longtext
表示的字符串長度不一樣。

2.4.3 枚舉(enum)


Enum,限制了當前的數據,看上去是一個字符串,其實保存的是整型(默認從1開始計數),最多允許有65535個枚舉項,也就是2個字節(但是會有一些其他的消耗,最終不能達到65536長度

創建枚舉表enmu_1:
mysql> create table if not exists enum_1(
    -> `e` enum('female', 'male')
    -> );
Query OK, 0 rows affected (0.06 sec)

插入數據方式1:
mysql> insert into enum_1 values('female');
Query OK, 1 row affected (0.02 sec)

mysql> insert into enum_1 values('male');
Query OK, 1 row affected (0.02 sec)

插入數據方式2:
mysql> insert into enum_1 values(2);
Query OK, 1 row affected (0.02 sec)

mysql> insert into enum_1 values(1);
Query OK, 1 row affected (0.01 sec)


數據展示1:
mysql> select * from enum_1;
+--------+
| e      |
+--------+
| female |
| male   |
| male   |
| female |
+--------+
4 rows in set (0.00 sec)

數據展示2:
mysql> select e+0 from enum_1;
+------+
| e+0  |
+------+
|    1 |
|    2 |
|    2 |
|    1 |
+------+
4 rows in set (0.00 sec)


2.4.4 set集合(相當於多項選擇題)


創建set表:
mysql> create table if not exists set_1(
    -> `s` set('A', 'B', 'C', 'D')
    -> );
Query OK, 0 rows affected (0.06 sec)

插入數據:
mysql> insert into set_1 values('A');
Query OK, 1 row affected (0.03 sec)

mysql> insert into set_1 values('A,B');
Query OK, 1 row affected (0.02 sec)

mysql> insert into set_1 values('C');
Query OK, 1 row affected (0.01 sec)

mysql> insert into set_1 values('C,D');
Query OK, 1 row affected (0.01 sec)

數據展示1:
mysql> select * from set_1;
+------+
| s    |
+------+
| A    |
| A,B  |
| C    |
| C,D  |
+------+

數據展示2:
mysql> select s+0 from set_1;
+------+
| s+0  |
+------+
|    1 |
|    3 |
|    4 |
|   12 |
+------+
4 rows in set (0.00 sec)

數據展示2的分析:set總共佔據8個字節,也就是64爲二進制數字,列表中每個參數佔據一位,也就是說最多保存64中狀態。
上述參數中的二進制存儲方式爲(1,10,100,1000),所以會出現數據展示2中的情況。


總結:



  • 應該使用最精確的類型。佔用的空間少。
  • 還應該考慮到相關應用語言的處理。例如常常將時間日期保存成一個整型。便於計算。
  • 考慮移植的兼容性。






























類型


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章