1. 程式人生 > >mysql從頭學一 1.0資料型別-數值型別

mysql從頭學一 1.0資料型別-數值型別

數值型別

MySQL 支援所有標準 SQL 中的數值型別,其中包括嚴格數值型別(INTEGER、SMALLINT、 DECIMAL 和 NUMERIC),以及近似數值資料型別(FLOAT、REAL 和 DOUBLE PRECISION),並在此基礎上做了擴充套件。擴充套件後增加了 TINYINT、MEDIUMINT 和 BIGINT 這 3 種長度不同的整型,並增加了 BIT 型別,用來存放位資料。表 3-1 中列出了 MySQL 5.0 中支援的所有數值型別,其中 INT 是 INTEGER 的同名詞,DEC 是 DECIMAL 的同名詞。

表 3-1                                               MySQL 中的數值型別

整數型別

位元組

最小值

最大值

TINYINT

1

有符號-128 無符號 0

有符號 127 無符號 255

SMALLINT

2

有符號-32768 無符號 0

有符號 32767 無符號 65535

MEDIUMINT

3

有符號-8388608 無符號 0

有符號 8388607 無符號 1677215

INT、INTEGER

4

有符號-2147483648 無符號 0

有符號 2147483647 無符號 4294967295

BIGINT

8

有符號-9223372036854775808 無符號 0

有符號 9223372036854775807 無符號 18446744073709551615

浮點數型別

位元組

最小值

最大值

FLOAT

4

±1.175494351E-38

±3.402823466E+38

DOUBLE

8

±2.2250738585072014E-308

±1.7976931348623157E+308

定點數型別

位元組

描述

DEC(M,D), DECIMAL(M,D)

M+2

最大取值範圍與 DOUBLE 相同,給定 DECIMAL 的有效取值範圍由 M 和 D 決定

位型別

位元組

最小值

最大值

BIT(M)

1~8

BIT(1)

BIT(64)

 

    在整數型別中,按照取值範圍和儲存方式不同,分為 tinyint、smallint、mediumint、int、 bigint 這 5 個型別。如果超出類型範圍的操作,會發生“Out of range”錯誤提示。為了避免此類問題發生,在選擇資料型別時要根據應用的實際情況確定其取值範圍,最後根據確定的結果慎重選擇資料型別。

    對於整型資料,MySQL 還支援在型別名稱後面的小括號內指定顯示寬度,例如 int(5)表示當數值寬度小於 5 位的時候在數字前面填滿寬度,如果不顯示指定寬度則預設為 int(11)。一般配合 zerofill 使用,顧名思義,zerofill 就是用“0”填充的意思,也就是在數字位數不夠的空間用字元“0”填滿。以下幾個例子分別描述了填充前後的區別。

  1. 建立表 t1,有 id1 和 id2 兩個欄位,指定其數值寬度分別為 int 和 int(5)。

mysql> create table t1 (id1 int,id2 int(5)); Query OK, 0 rows affected (0.03 sec) mysql> desc t1;

+-------+---------+------+-----+---------+-------+

| Field | Type    | Null | Key | Default | Extra |

+-------+---------+------+-----+---------+-------+

| id1   | int(11) | YES  |     | NULL    |       | 

| id2   | int(5)  | YES  |     | NULL    |       | 

+-------+---------+------+-----+---------+-------+

2 rows in set (0.00 sec)

  1. 在 id1 和 id2 中都插入數值 1,可以發現格式沒有異常。

mysql> insert into t1 values(1,1);

Query OK, 1 row affected (0.00 sec)

 mysql> select * from t1;

+------+------+

| id1  | id2  |

+------+------+

|    1 |    1 | 

+------+------+

1 row in set (0.00 sec)

  1. 分別修改 id1 和 id2 的欄位型別,加入 zerofill 引數:

mysql> alter table t1 modify id1 int zerofill;

Query OK, 1 row affected (0.04 sec)

Records: 1  Duplicates: 0  Warnings: 0

 

mysql> alter table t1 modify id2 int(5) zerofill;

Query OK, 1 row affected (0.03 sec)

Records: 1  Duplicates: 0  Warnings: 0

 mysql> select * from t1; +------------+-------+

| id1        | id2   |

+------------+-------+

| 0000000001 | 00001 |  +------------+-------+

1 row in set (0.00 sec)

可以發現,在數值前面用字元“0”填充了剩餘的寬度。大家可能會有所疑問,設定了寬度限制後,如果插入大於寬度限制的值,會不會截斷或者插不進去報錯?答案是肯定的:不會對插入的資料有任何影響,還是按照型別的實際精度進行儲存,這是,寬度格式實際已經沒有意義,左邊不會再填充任何的“0”字元。下面在表 t1 的欄位 id1 中插入數值 1,id2 中插入數值 1111111,位數為 7,大於 id2 的顯示位數 5,再觀察一下測試結果:

mysql> insert into t1 values(1,1111111);

Query OK, 1 row affected (0.00 sec)

 mysql> select * from t1; +------------+---------+

| id1        | id2     |

+------------+---------+

| 0000000001 |   00001 | 

| 0000000001 | 1111111 | 

+------------+---------+

2 rows in set (0.00 sec)

很顯然,如上面所說,id2 中顯示了正確的數值,並沒有受寬度限制影響。

    所有的整數型別都有一個可選屬性 UNSIGNED(無符號),如果需要在欄位裡面儲存非負數或者需要較大的上限值時,可以用此選項,它的取值範圍是正常值的下限取 0,上限取原值的 2 倍,例如,tinyint 有符號範圍是-128~+127,而無符號範圍是 0~255。如果一個列指定為 zerofill,則 MySQL 自動為該列新增 UNSIGNED 屬性。

 另外,整數型別還有一個屬性:AUTO_INCREMENT。在需要產生唯一識別符號或順序值時,可利用此屬性,這個屬性只用於整數型別。AUTO_INCREMENT 值一般從 1 開始,每行增加 1。在插入 NULL 到一個 AUTO_INCREMENT 列時,MySQL 插入一個比該列中當前最大值大 1 的值。一個表中最多隻能有一個AUTO_INCREMENT列。對於任何想要使用AUTO_INCREMENT 的列,應該定義為 NOT NULL,並定義為 PRIMARY KEY 或定義為 UNIQUE 鍵。例如,可按下列任何一種方式定義 AUTO_INCREMENT 列:

CREATE TABLE  AI (ID INT AUTO_INCREMENT NOT NULL PRIMARY KEY);

CREATE  TABLE  AI(ID INT AUTO_INCREMENT NOT NULL ,PRIMARY KEY(ID));

CREATE  TABLE  AI (ID INT AUTO_INCREMENT NOT NULL ,UNIQUE(ID));

    對於小數的表示,MySQL 分為兩種方式:浮點數和定點數。浮點數包括 float(單精度)和 double(雙精度),而定點數則只有 decimal 一種表示。定點數在 MySQL 內部以字串形式存放,比浮點數更精確,適合用來表示貨幣等精度高的資料。

 浮點數和定點數都可以用型別名稱後加“(M,D)”的方式來進行表示,“(M,D)”表示該值一共顯示 M 位數字(整數位+小數位),其中 D 位位於小數點後面,M D 又稱為精度和標度。例如,定義為 float(7,4)的一個列可以顯示為-999.9999。MySQL 儲存值時進行四捨五入,因此如果在 float(7,4)列內插入 999.00009,近似結果是 999.0001。值得注意的是,浮點數後面跟“(M,D)”的用法是非標準用法,如果要用於資料庫的遷移,則最好不要這麼使用。 float 和 double 在不指定精度時,預設會按照實際的精度(由實際的硬體和作業系統決定)來顯示,而 decimal 在不指定精度時,預設的整數位為 10,預設的小數位為 0。  下面通過一個例子來比較 float、double 和 decimal 三者之間的不同。 

  1. 建立測試表,分別將 id1、id2、id3 欄位設定為 float(5,2)、double(5,2)、decimal(5,2)。

CREATE TABLE `t1` (

  `id1` float(5,2) default NULL,

  `id2` double(5,2) default NULL,

  `id3` decimal(5,2) default NULL )

  1. 往 id1、id2 和 id3 這 3 個欄位中插入資料 1.23。

mysql> insert into t1 values(1.23,1.23,1.23);

Query OK, 1 row affected (0.00 sec)

 mysql>  mysql> select * from t1; +------+------+------+

| id1  | id2  | id3  |

+------+------+------+

| 1.23 | 1.23 | 1.23 |  +------+------+------+

1 row in set (0.00 sec)

可以發現,資料都正確地插入了表 t1。

  1. 再向 id1 和 id2 欄位中插入資料 1.234,而 id3 欄位中仍然插入 1.23。

mysql> insert into t1 values(1.234,1.234,1.23);

Query OK, 1 row affected (0.00 sec)

 mysql> select * from t1; +------+------+------+

| id1  | id2  | id3  |

+------+------+------+

| 1.23 | 1.23 | 1.23 | 

| 1.23 | 1.23 | 1.23 | 

+------+------+------+

2 rows in set (0.00 sec)

可以發現,id1、id2、id3 都插入了表 t1,但是 id1 和 id2 由於標度的限制,捨去了最後一位,資料變為了 1.23。

  1. 同時向 id1、id2、id3 欄位中都插入資料 1.234。

mysql> insert into t1 values(1.234,1.234,1.234);

Query OK, 1 row affected, 1 warning (0.00 sec)

 

mysql> show warnings;

+-------+------+------------------------------------------+

| Level | Code | Message                                  |

+-------+------+------------------------------------------+

| Note  | 1265 | Data truncated for column 'id3' at row 1 | 

+-------+------+------------------------------------------+

1 row in set (0.00 sec)

 mysql> select * from t1; +------+------+------+

| id1  | id2  | id3  |

+------+------+------+

| 1.23 | 1.23 | 1.23 | 

| 1.23 | 1.23 | 1.23 | 

| 1.23 | 1.23 | 1.23 | 

+------+------+------+

3 rows in set (0.00 sec)

此時發現,雖然資料都插入進去,但是系統出現了一個 warning,報告 id3 被截斷。如果是在傳統的 SQLMode(第 16 章將會詳細介紹 SQLMode)下,這條記錄是無法插入的。

  1. 將 id1、id2、id3 欄位的精度和標度全部去掉,再次插入資料 1.23。

mysql> alter table t1 modify id1 float; Query OK, 3 rows affected (0.03 sec)

Records: 3  Duplicates: 0  Warnings: 0

 

mysql> alter table t1 modify id2 double; Query OK, 3 rows affected (0.04 sec)

Records: 3  Duplicates: 0  Warnings: 0

 

mysql> alter table t1 modify id3 decimal;

Query OK, 3 rows affected, 3 warnings (0.02 sec) Records: 3  Duplicates: 0  Warnings: 0 mysql> desc t1;

+-------+---------------+------+-----+---------+-------+

| Field | Type          | Null | Key | Default | Extra |

+-------+---------------+------+-----+---------+-------+

| id1   | float         | YES  |     | NULL    |       | 

| id2   | double        | YES  |     | NULL    |       | 

| id3   | decimal(10,0) | YES  |     | NULL    |       | 

+-------+---------------+------+-----+---------+-------+

3 rows in set (0.00 sec)

 

mysql> insert into t1 values(1.234,1.234,1.234);

Query OK, 1 row affected, 1 warning (0.00 sec)

 

mysql> show warnings;

+-------+------+------------------------------------------+

| Level | Code | Message                                  |

+-------+------+------------------------------------------+

| Note  | 1265 | Data truncated for column 'id3' at row 1 | 

+-------+------+------------------------------------------+

1 row in set (0.00 sec)

 mysql> select * from t1; +-------+-------+------+

| id1   | id2   | id3  |

+-------+-------+------+

| 1.234 | 1.234 |    1 | 

+-------+-------+------+

1 row in set (0.00 sec)

這個時候,可以發現 id1、id2 欄位中可以正常插入資料,而 id3 欄位的小數位被截斷。

 

上面這個例子驗證了上面提到的浮點數如果不寫精度和標度,則會按照實際精度值顯示,如果有精度和標度,則會自動將四捨五入後的結果插入,系統不會報錯;定點數如果不寫精度和標度,則按照預設值 decimal(10,0)來進行操作,並且如果資料超越了精度和標度值,系統則會報錯。

對於 BIT(位)型別,用於存放位欄位值,BIT(M)可以用來存放多位二進位制數,M 範圍從 1~ 64,如果不寫則預設為 1 位。對於位欄位,直接使用 SELECT 命令將不會看到結果,可以用 bin()(顯示為二進位制格式)或者 hex()(顯示為十六進位制格式)函式進行讀取。

下面的例子中,對測試表 t2 中的 bit 型別欄位 id 做 insert 和 select 操作,這裡重點觀察一下 select 的結果:

mysql> desc t2;

+-------+--------+------+-----+---------+-------+

| Field | Type   | Null | Key | Default | Extra |

+-------+--------+------+-----+---------+-------+

| id    | bit(1) | YES  |     | NULL    |       | 

+-------+--------+------+-----+---------+-------+

1 row in set (0.00 sec)

 

mysql> insert into t2 values(1); Query OK, 1 row affected (0.00 sec) mysql> select * from t2;

+------+

| id   |

+------+

|     | 

+------+

1 row in set (0.00 sec)

 

可以發現,直接 select * 結果為 NULL。改用 bin()和 hex()函式再試試:

mysql> select bin(id),hex(id) from t2;

+---------+---------+

| bin(id) | hex(id) |

+---------+---------+

| 1       | 1       | 

+---------+---------+

1 row in set (0.00 sec)

結果可以正常顯示為二進位制數字和十六進位制數字。

資料插入 bit 型別欄位時,首先轉換為二進位制,如果位數允許,將成功插入;如果位數小於實際定義的位數,則插入失敗,下面的例子中,在 t2 表插入數字 2,因為它的二進位制碼是

“10”,而 id 的定義是 bit(1),將無法進行插入:

mysql> insert into t2 values(2);

Query OK, 1 row affected, 1 warning (0.00 sec)

 

mysql> show warnings;

+---------+------+------------------------------------------------------+

| Level   | Code | Message                                              |

+---------+------+------------------------------------------------------+

| Warning | 1264 | Out of range value adjusted for column 'id' at row 1 | 

+---------+------+------------------------------------------------------+

  1. row in set (0.01 sec)

將 ID 定義修改為 bit(2)後,重新插入,插入成功:

mysql> alter table t2 modify id bit(2); Query OK, 1 row affected (0.02 sec)

Records: 1  Duplicates: 0  Warnings: 0

 mysql> insert into t2 values(2);

Query OK, 1 row affected (0.00 sec)

 mysql> select bin(id),hex(id) from t2;

+---------+---------+

| bin(id) | hex(id) |

+---------+---------+

| 1       | 1       | 

| 10      | 2       | 

+---------+---------+

  1. rows in set (0.00 sec)