MySQL基礎篇(2)數據類型

  MySQL提供了多種數據類型,主要包括數值型、字符串類型、日期和時間類型。mysql

  1.數值類型sql

  • 整數類型:TINYINT(1字節)、SMALLINT(2字節)、MEDIUMINT(3字節)、INT(INTEGER)(4字節)、BIGINT(8字節)
  • 浮點類型:FLOAT(4字節)、DOUBLE(8字節)
  • 定點數類型:DEC(M,D)(M + 2字節)、DECIMAL(M,D)(M+2字節)
  • 位類型:BIT(M)(1~8字節)

  (1)整數類型網絡

  MySQL支持在類型名稱後面的小括號內指定顯示寬度,例如int(5)表示當數值寬度小於5位的時候在數字前面填滿寬度,若是指示顯示寬度則默認爲int(11)。通常配合zerofill使用,zerofill就是用‘0’填充的意思,也就是在數字位數不夠的空間用字符‘0’填滿。ide

mysql> create table t1(id1 int, id2 int(5));
Query OK, 0 rows affected (0.01 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)

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

mysql> select * from t1;
+------+------+
| id1  | id2  |
+------+------+
|    1 |    1 |
+------+------+
1 row in set (0.00 sec)

mysql> alter table t1 modify id1 int zerofill;
Query OK, 1 row affected (0.06 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> alter table t1 modify id2 int(5) zerofill;
Query OK, 1 row affected (0.06 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+------------+-------+
| id1        | id2   |
+------------+-------+
| 0000000001 | 00001 |
+------------+-------+
1 row in set (0.00 sec)

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

mysql> select * from t1;
+------------+---------+
| id1        | id2     |
+------------+---------+
| 0000000001 |   00001 |
| 0000000001 | 1111111 |
+------------+---------+
2 rows in set (0.00 sec)
顯示寬度與ZEROFILL

  若是插入大於寬度限制的值,例如int(5)的屬性值插入爲1111111,那麼此時顯示寬度將沒有意義,而是按照實際的精度進行保存。函數

  UNSIGNED:全部的整數類型都有一個可選屬性UNSIGNED(無符號),若是須要在字段裏面保存非負數或者較大的上限值時,可使用此選項。例如,tinyint(1字節)的有符號的範圍是-128~+127,而無符號的範圍就是0~255。若是一個列指定爲zerofill,則MySQL自動爲該列添加UNSIGNED屬性。性能

  AUTO_INCREMENT:在須要產生惟一標識符或順序值時,可使用此屬性,這個屬性只用於整數類型。AUTO_INCREMENT值通常從1開始,每行增長1。一個表中最多隻能有一個AUTO_INCREMENT列,同時該列應該定義爲NOT NULL,並定義爲PRIMARY KEY或者UNIQUE鍵。測試

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));

  (2)小數類型:浮點數和定點數spa

  浮點數包括float(單精度)、double(雙精度),3d

  定點數則只有decimal一種表示,頂點數在MySQL內部是以字符串形式存放,比浮點數更精確,適合用來表示貨幣等精度高的數據。code

  浮點數和定點數均可以用類型名稱後加「(M,D)」來表示該值一共顯示M位數字(整數位+小數位),其中D位位於小數點後面,M和D又稱爲精度和標度。

  例如,定義爲float(7,4)的一個列能夠顯示爲-999.9999,而若是要插入999.00009,則會四捨五入近似結果爲999.0001

  float和double在不指定精度時,默認會按照實際的精度來顯示,而decimal在不指定精度時,默認的整數位爲10,默認的小數位爲0

  假設在float,double,decimal中插入1.234,1.234,1.234,則前兩個會按照實際精度值顯示成1.234,而因爲最後一個默認decimal(10,0)就會顯示成1

  假設在float(5,2),double(5,2),decimal(5,2)中插入1.234,1.234,1.234,則前兩個數會四捨五入爲1.23,最後一個雖然會報警,然而仍是按照實際精度四捨五入後插入。

  假設在float(10,2),decimal(10,2)中插入131072.32,131072.32後前一個數會插入131072.31,後一個數會插入131072.32,這是由於使用單精度浮點數產生了偏差。

  如何選擇合適的數據類型:

  使用浮點型數據保存小數時,會有可能產生偏差。在精度要求比較高的應用中(好比貨幣)要使用定點數而不是浮點數來保存數據。

  (3)位類型

  位類型能夠用於存放字段值,BIT(M)能夠用來存放多位二進制數,M範圍從1~64,若是不寫則默認爲1位。對於位字段,直接使用select命令將不會看到結果,能夠用bin()顯示爲二進制格式或者hex()顯示爲十六進制格式函數進行讀取。

  數據插入bit類型字段時,首先轉換爲二進制,若是位數容許,將成功插入;若是位數超過定義的位數,則插入失敗。例如bit默認類型插入2會插入失敗,由於2轉換成二進制後是「10」,而bit默認位數爲1,將bit修改爲bit(2)便可插入。

mysql> create table t3(id bit);
Query OK, 0 rows affected (0.02 sec)

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

mysql> select * from t3;
+------+
| id   |
+------+
|     |
+------+
1 row in set (0.00 sec)

mysql> select bin(id),hex(id) from t3;
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 1       | 1       |
+---------+---------+
1 row in set (0.00 sec)

mysql> insert into t3 value(2);
ERROR 1406 (22001): Data too long for column 'id' at row 1
mysql> desc t3;
+-------+--------+------+-----+---------+-------+
| Field | Type   | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+-------+
| id    | bit(1) | YES  |     | NULL    |       |
+-------+--------+------+-----+---------+-------+
1 row in set (0.00 sec)

mysql> alter table t3 modify id bit(2);
Query OK, 1 row affected (0.07 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into t3 value(2);
Query OK, 1 row affected (0.01 sec)

mysql> select bin(id),hex(id) from t3;
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 1       | 1       |
| 10      | 2       |
+---------+---------+
2 rows in set (0.00 sec)
bit位類型使用示例

 

  2.日期時間類型

  • DATE(4字節):表示年月日,1000-01-01  ~ 9999-12-31
  • DATETIME(8字節):表示年月日時分秒,1000-01-01 00:00:00 ~ 9999-12-31 23:59:59
  • TIME(3字節):表示時分秒,-838:59:59 ~ 838:59:59
  • TIMESTAMP(4字節):須要常常插入或者更新日期爲當前系統時間,19700101080001 ~ 2038年的某個時刻,可是查詢顯示的結果是相似「0000-00-00 00:00:00」的字符串
  • YEAR(1字節):表示年份,默認是4位格式,1901 ~ 2155

  TIMESTAMP和DATETIME的區別:

  • TIMESTAMP支持的時間範圍很小,DATATIME範圍更大。
  • 表中的第一個TIMESTAMP列自動設置爲系統時間,若是在一個TIMESTAMP中插入null,則該列值也會自動設置該列的值爲當前的時間;在插入或更新一行但不明確給TIMESTAMP賦值時也會自動設置該列的值爲當前的日期和時間,當插入的值超出取值範圍時,用「0000-00-00 00:00:00」填充。
  • TIMESTAMP的插入和查詢都受當地時區的影響,更能反映出實際的日期,而DATATIME則只能反映出插入時當地的時區。

  日期類型的插入格式有不少種,下面的幾種都是能夠的(假設create table t6(dt datetime);):

  • 嚴格語法的字符串:insert into t6 values('2007-9-3 12:10:10');
  • 不嚴格語法的字符串:insert into t6 value('2007!9@3 12$10%10');
  • 沒有間隔的數字字符串:insert into t6 value('20070903121010');
  • 純數字:insert into t6 value(20070903121010);
  • 函數返回的結果:insert into t6 value(now());

 

  3.字符串類型

  MySQL中提供了多種對字符數據的存儲類型

  (1)CHAR和VARCHAR類型

  都用來保存MySQL中較短的字符串,兩者的主要區別在於存儲方式的不一樣:

  CHAR列的長度固定位建立表時聲明的長度,長度能夠從0~255的任何值;而VARCHAR列中的值爲可變長字符串,長度能夠指定爲0~255或者65536之間的值。

  在檢索的時候,CHAR列刪除了尾部的空格,而VARCHAR則保留了這些空格。

  如何選擇合適的數據類型:

  CHAR屬於固定長度的字符類型,而VARCHAR屬於可變長度的字符類型。

  因爲CHAR是固定長度的,因此它的處理速度比VARCHAR快得多,可是其缺點是浪費存儲空間,程序須要對行尾空格進行處理,因此對於那些長度變化不大而且對查詢速度有較高要求的數據能夠考慮使用CHAR類型來存儲。

  對於不一樣類型的存儲引擎來講:

  • MyISAM和MEMORY:使用固定長度的數據列代替可變長度的數據列
  • InnoDB:使用VARCHAR類型。(行存儲格式不區分固定和可變,而且存儲容量和磁盤I/O比較好)

  (2)BINARY和VARBINARY類型

  它們包含二進制字符串而不包含非二進制字符串。在保存BINARY值時,在值的最後經過填充「0x00」以達到指定的字段定義長度。

  (3)ENUM類型

  它的值範圍須要在建立表時經過枚舉方式顯示指定,對1~255個成員的枚舉須要1個字節存儲;對於255~65535個成員,須要2個字節存儲。最多容許65535個成員。

  建立測試表t,定義gender字段爲枚舉類型,成員爲'M'和'F',由結果能夠看到,ENUM是忽略大小寫的,當插入在'M'和'F'中間的某個值('M')和('f')時,能夠成功插入,而插入一個不在ENUM成員中的值時,並無返回警告也不會報錯,而是插入了ENUM中的第一個值'M'。

mysql> create table t(gender enum('M','F'));
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t;
Empty set (0.00 sec)

mysql> insert into t values('M'),('1'),('f'),(NULL);
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from t;
+--------+
| gender |
+--------+
| M      |
| M      |
| F      |
| NULL   |
+--------+
4 rows in set (0.00 sec)
ENUM類型使用示例  

  (4)SET類型

  SET和ENUM類型很是相似,也是一個字符串對象,裏面能夠包含0~64個成員。

  根據成員數量的不一樣,分爲1~8(1字節)、9~16(2字節)、17~24(3字節)、25~32(4字節)、33~64(8字節)

  SET和ENUM最主要的區別就是SET類型一次能夠選取多個成員,而ENUM只能選取一個。

  對於在set中的值,均可以被成功地插入,若是不在,就會報錯;對於重複的對象,例如('a,d,a')在插入以後會去重變成「a,d」。

mysql> create table setTest(col set('a','b','c','d'));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into setTest values('a,b'),('a,d,a'),('a,b'),('a,c'),('a'),('a,e'),('e');
ERROR 1265 (01000): Data truncated for column 'col' at row 6
mysql> insert into setTest values('a,b'),('a,d,a'),('a,b'),('a,c'),('a'),('a,e');
ERROR 1265 (01000): Data truncated for column 'col' at row 6
mysql> insert into setTest values('a,b'),('a,d,a'),('a,b'),('a,c'),('a');
Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from setTest;
+------+
| col  |
+------+
| a,b  |
| a,d  |
| a,b  |
| a,c  |
| a    |
+------+
5 rows in set (0.00 sec)
SET類型使用示例

   (5)TEXT與BLOB

  通常在保存少許字符串的時候,會選擇CHAR或者VARCHAR;而在保存較大文本時,一般會選擇使用TEXT或BLOB。

  區別就是BLOB能夠用來保存二進制數據,好比照片;而TEXT只能保存字符數據,好比一篇文章或者日記。

  TEXT又分爲TEXT、MEDIUMTEXT、LONGTEXT,BLOB又分爲BLOB、MEDIUMBLOB、LONGBLOB。有一些常見問題:

  • BLOB和TEXT值會引發一些性能問題,特別是在執行了大量的刪除操做時。刪除操做會在數據表中留下很大的「空洞」,之後填入這些「空洞」的記錄在插入的性能上會有影響。爲了提升性能,建議按期使用[OPTIMIZE TABLE 表名]功能對這類表進行碎片整理,避免由於「空洞」致使性能問題。
  • 可使用合成的(Synthetic)索引來提升BLOB或TEXT的查詢性能。合成索引就是根據大文本字段的內容創建一個散列值,並把這個值存儲在單獨的數據列中,查詢的時候就能夠經過檢索散列值定位到數據了。這種技術只能用於精確匹配,在必定從程度上減小了I/O,提升了查詢效率。若是須要對BLOB字段進行模糊查詢,就可使用前綴索引,也就是隻爲字段的前n列建立索引,例如create index idx on t(context(100))就是爲字段的前100個字符建立索引,而後使用like進行模糊查詢便可。
    mysql> create table t(id varchar(100), context blob, hash_value varchar(40));
    Query OK, 0 rows affected (0.05 sec)
    
    mysql> insert into t values(1,repeat('beijing',2),md5(context));
    Query OK, 1 row affected (0.03 sec)
    
    mysql> insert into t values(2,repeat('beijing',2),md5(context));
    Query OK, 1 row affected (0.01 sec)
    
    mysql> insert into t values(3,repeat('beijing_2008',2),md5(context));
    Query OK, 1 row affected (0.03 sec)
    
    mysql> select * from t;
    +------+--------------------------+----------------------------------+
    | id   | context                  | hash_value                       |
    +------+--------------------------+----------------------------------+
    | 1    | beijingbeijing           | 09746eef633dbbccb7997dfd795cff17 |
    | 2    | beijingbeijing           | 09746eef633dbbccb7997dfd795cff17 |
    | 3    | beijing_2008beijing_2008 | ab35be94cba8e0d4c51740c5d21640d4 |
    +------+--------------------------+----------------------------------+
    3 rows in set (0.00 sec)
    
    mysql> select  * from t where hash_value=md5(repeat('beijing_2008',2));
    +------+--------------------------+----------------------------------+
    | id   | context                  | hash_value                       |
    +------+--------------------------+----------------------------------+
    | 3    | beijing_2008beijing_2008 | ab35be94cba8e0d4c51740c5d21640d4 |
    +------+--------------------------+----------------------------------+
    1 row in set (0.00 sec)
    合成索引舉例
mysql> create index idx_blob on t(context(100));
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> select * from t where context like 'beijing%';
+------+--------------------------+----------------------------------+
| id   | context                  | hash_value                       |
+------+--------------------------+----------------------------------+
| 1    | beijingbeijing           | 09746eef633dbbccb7997dfd795cff17 |
| 2    | beijingbeijing           | 09746eef633dbbccb7997dfd795cff17 |
| 3    | beijing_2008beijing_2008 | ab35be94cba8e0d4c51740c5d21640d4 |
+------+--------------------------+----------------------------------+
3 rows in set (0.00 sec)

mysql> desc select * from t where context like 'beijing%' \G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: t
   partitions: NULL
         type: ALL
possible_keys: idx_blob
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where
1 row in set, 1 warning (0.00 sec)
前綴索引舉例
  • 在沒必要要的時候避免檢索大型的BLOB或TEXT值。select * 直接查詢就不是很好的想法,除非可以肯定做爲約束條件的WHERE字句只會找到所須要的數據行。
  • 把BLOB或TEXT列分離到單獨的表中。若是把數據列移動到第二章數據表中,能夠把原數據表中的數據列轉換成固定長度的數據行格式,這會減小主表中的碎片,能夠獲得固定長度數據行的性能優點,還能夠是主數據表在執行select * 查詢的時候不會經過網絡傳輸大量的BLOB或TEXT值。
相關文章
相關標籤/搜索