MySQL基礎數據類型

一 介紹

  存儲引擎決定了表的類型,而表內存放的數據也要有不一樣的類型,每種數據類型都有本身的寬度,但寬度是可選的html

  詳細參考:前端

  • http://www.runoob.com/mysql/mysql-data-types.html
  • http://dev.mysql.com/doc/refman/5.7/en/data-type-overview.html

  mysql經常使用數據類型概覽:mysql

#1. 數字:
    整型:tinyinit  int  bigint
    小數:
        float :在位數比較短的狀況下不精準
        double :在位數比較長的狀況下不精準
            0.000001230123123123
            存成:0.000001230000

        decimal:(若是用小數,則用推薦使用decimal)
            精準
            內部原理是以字符串形式去存

#2. 字符串:
    char(10):簡單粗暴,浪費空間,存取速度快
        root存成root000000
    varchar:精準,節省空間,存取速度慢

    sql優化:建立表時,定長的類型往前放,變長的日後放
                    好比性別           好比地址或描述信息

    >255個字符,超了就把文件路徑存放到數據庫中。
            好比圖片,視頻等找一個文件服務器,數據庫中只存路徑或url。



#3. 時間類型:
    最經常使用:datetime


#4. 枚舉類型與集合類型

二 數值類型

  一、整數類型sql

    整數類型:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT數據庫

    做用:存儲年齡,等級,id,各類號碼等服務器

tinyint[(m)] [unsigned] [zerofill]

            小整數,數據類型用於保存一些範圍的整數數值範圍:
            有符號:
                -128 ~ 127
            無符號:
                0 ~ 255

            PS: MySQL中無布爾值,使用tinyint(1)構造。



        int[(m)][unsigned][zerofill]

            整數,數據類型用於保存一些範圍的整數數值範圍:
            有符號:
                    -2147483648 ~ 2147483647
            無符號:
                    0 ~ 4294967295



        bigint[(m)][unsigned][zerofill]
            大整數,數據類型用於保存一些範圍的整數數值範圍:
            有符號:
                    -9223372036854775808 ~ 9223372036854775807
            無符號:
                    0  ~  18446744073709551615
有符號和無符號tinyint
    1.tinyint默認爲有符號
        mysql> create table t1(x tinyint); #默認爲有符號,即數字前有正負號
        mysql> desc t1;
        mysql> insert into t1 values
            -> (-129),
            -> (-128),
            -> (127),
            -> (128);
        mysql> select * from t1;
        +------+
        | x    |
        +------+
        | -128 | #-129存成了-128
        | -128 | #有符號,最小值爲-128
        |  127 | #有符號,最大值127
        |  127 | #128存成了127
        +------+



    2.設置無符號tinyint
        mysql> create table t2(x tinyint unsigned);
        mysql> insert into t2 values
            -> (-1),
            -> (0),
            -> (255),
            -> (256);
        mysql> select * from t2;
        +------+
        | x    |
        +------+
        |    0 | -1存成了0
        |    0 | #無符號,最小值爲0
        |  255 | #無符號,最大值爲255
        |  255 | #256存成了255
        +------+



有符號和無符號int
    1.int默認爲有符號
        mysql> create table t3(x int); #默認爲有符號整數
        mysql> insert into t3 values
            -> (-2147483649),
            -> (-2147483648),
            -> (2147483647),
            -> (2147483648);
        mysql> select * from t3;
        +-------------+
        | x           |
        +-------------+
        | -2147483648 | #-2147483649存成了-2147483648
        | -2147483648 | #有符號,最小值爲-2147483648
        |  2147483647 | #有符號,最大值爲2147483647
        |  2147483647 | #2147483648存成了2147483647
        +-------------+



    2.設置無符號int
        mysql> create table t4(x int unsigned);
        mysql> insert into t4 values
            -> (-1),
            -> (0),
            -> (4294967295),
            -> (4294967296);
        mysql> select * from t4;
        +------------+
        | x          |
        +------------+
        |          0 | #-1存成了0
        |          0 | #無符號,最小值爲0
        | 4294967295 | #無符號,最大值爲4294967295
        | 4294967295 | #4294967296存成了4294967295
        +------------+




有符號和無符號bigint
    1.有符號bigint
        mysql> create table t6(x bigint);
        mysql> insert into t5 values  
            -> (-9223372036854775809),
            -> (-9223372036854775808),
            -> (9223372036854775807),
            -> (9223372036854775808);

        mysql> select * from t5;
        +----------------------+
        | x                    |
        +----------------------+
        | -9223372036854775808 |
        | -9223372036854775808 |
        |  9223372036854775807 |
        |  9223372036854775807 |
        +----------------------+


    2.無符號bigint
        mysql> create table t6(x bigint unsigned);
        mysql> insert into t6 values  
            -> (-1),
            -> (0),
            -> (18446744073709551615),
            -> (18446744073709551616);

        mysql> select * from t6;
        +----------------------+
        | x                    |
        +----------------------+
        |                    0 |
        |                    0 |
        | 18446744073709551615 |
        | 18446744073709551615 |
        +----------------------+




用zerofill測試整數類型的顯示寬度
    mysql> create table t7(x int(3) zerofill);
    mysql> insert into t7 values
        -> (1),
        -> (11),
        -> (111),
        -> (1111);
    mysql> select * from t7;
    +------+
    | x    |
    +------+
    |  001 |
    |  011 |
    |  111 |
    | 1111 | #超過寬度限制仍然能夠存
    +------+

    注意:對於整型來講,數據類型後面的寬度並非存儲長度限制,而是顯示限制,假如:int(8),那麼顯示時不夠8位則用0來填充,夠8位則正常顯示,經過zerofill來測試,存儲長度仍是int的4個字節長度。默認的顯示寬度就是可以存儲的最大的數據的長度,好比:int無符號類型,那麼默認的顯示寬度就是int(10),有符號的就是int(11),由於多了一個符號,因此咱們沒有必要指定整數類型的數據,不必指定寬度,由於默認的就可以將你存的原始數據徹底顯示併發

    img

    int的存儲寬度是4個Bytes,即32個bit,即2**32  less

    無符號最大值爲:4294967296-1運維

    有符號最大值:2147483648-1socket

    有符號和無符號的最大數字須要的顯示寬度均爲10,而針對有符號的最小值則須要11位才能顯示徹底,因此int類型默認的顯示寬度爲11是很是合理的

    最後:整形類型,其實沒有必要指定顯示寬度,使用默認的就ok

說到這裏我想提一下MySQL的mode設置,看我這篇博客:https://www.cnblogs.com/clschao/articles/9962347.html,看完博客應該就能理解MySQL的mode了。

  二、浮點型

    定點數類型 DEC,等同於DECIMAL  

    浮點類型:FLOAT DOUBLE

    做用:存儲薪資、身高、溫度、體重、體質參數等

1.FLOAT[(M,D)] [UNSIGNED] [ZEROFILL]

    定義:
            單精度浮點數(非準確小數值),m是整數部分+小數部分的總個數,d是小數點後個數。m最大值爲255,d最大值爲30,例如:float(255,30)

    有符號:
               -3.402823466E+38 to -1.175494351E-38,
               1.175494351E-38 to 3.402823466E+38
    無符號:
               1.175494351E-38 to 3.402823466E+38


    精確度: 
               **** 隨着小數的增多,精度變得不許確 ****



2.DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL]

    定義:
               雙精度浮點數(非準確小數值),m是整數部分+小數部分的總個數,d是小數點後個數。m最大值也爲255,d最大值也爲30

    有符號:
               -1.7976931348623157E+308 to -2.2250738585072014E-308
               2.2250738585072014E-308 to 1.7976931348623157E+308

    無符號:
               2.2250738585072014E-308 to 1.7976931348623157E+308
                
    精確度:
               ****隨着小數的增多,精度比float要高,但也會變得不許確 ****


3.decimal[(m[,d])] [unsigned] [zerofill]

    定義:
              準確的小數值,m是整數部分+小數部分的總個數(負號不算),d是小數點後個數。 m最大值爲65,d最大值爲30。比float和double的整數個數少,可是小數位數都是30位


    精確度:
               **** 隨着小數的增多,精度始終準確 ****
               對於精確數值計算時須要用此類型
               decimal可以存儲精確值的緣由在於其內部按照字符串存儲。
精度從高到低:decimal、double、float
    decimal精度高,可是整數位數少
    float和double精度低,可是整數位數多
float已經知足絕大多數的場景了,可是什麼導彈、航線等要求精度很是高,因此仍是須要按照業務場景自行選擇,若是又要精度高又要整數位數多,那麼你能夠直接用字符串來存。
mysql> create table t1(x float(256,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t1(x float(256,30));
ERROR 1439 (42000): Display width out of range for column 'x' (max = 255)
mysql> create table t1(x float(255,30)); #建表成功
Query OK, 0 rows affected (0.02 sec)

mysql> create table t2(x double(255,30)); #建表成功
Query OK, 0 rows affected (0.02 sec)

mysql> create table t3(x decimal(66,31));
ERROR 1425 (42000): Too big scale 31 specified for column 'x'. Maximum is 30.
mysql> create table t3(x decimal(66,30));
ERROR 1426 (42000): Too-big precision 66 specified for 'x'. Maximum is 65.
mysql> create table t3(x decimal(65,30)); #建表成功
Query OK, 0 rows affected (0.02 sec)

mysql> show tables;
+---------------+
| Tables_in_db1 |
+---------------+
| t1            |
| t2            |
| t3            |
+---------------+
3 rows in set (0.00 sec)



mysql> insert into t1 values(1.1111111111111111111111111111111); #小數點後31個1
Query OK, 1 row affected (0.01 sec)

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

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

mysql> select * from t1; #隨着小數的增多,精度開始不許確
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111164093017600000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select * from t2; #精度比float要準確點,但隨着小數的增多,一樣變得不許確
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111200000000000000 |
+----------------------------------+
1 row in set (0.00 sec)

mysql> select * from t3; #精度始終準確,d爲30,因而只留了30位小數
+----------------------------------+
| x                                |
+----------------------------------+
| 1.111111111111111111111111111111 |
+----------------------------------+
1 row in set (0.00 sec)

  三、位類型(瞭解,不講~~)

    BIT(M)能夠用來存放多位二進制數,M範圍從1~64,若是不寫默認爲1位。
    注意:對於位字段須要使用函數讀取
    bin()顯示爲二進制
    hex()顯示爲十六進制

mysql> create table t9(id bit);
mysql> desc t9; #bit默認寬度爲1
+-------+--------+------+-----+---------+-------+
| Field | Type   | Null | Key | Default | Extra |
+-------+--------+------+-----+---------+-------+
| id    | bit(1) | YES  |     | NULL    |       |
+-------+--------+------+-----+---------+-------+

mysql> insert into t9 values(8);
mysql> select * from t9; #直接查看是沒法顯示二進制位的
+------+
| id   |
+------+
|     |
+------+
mysql> select bin(id),hex(id) from t9; #須要轉換才能看到
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 1       | 1       |
+---------+---------+

mysql> alter table t9 modify id bit(5);
mysql> insert into t9 values(8);
mysql> select bin(id),hex(id) from t9;
+---------+---------+
| bin(id) | hex(id) |
+---------+---------+
| 1       | 1       |
| 1000    | 8       |
+---------+---------+

三 日期類型

  類型:DATE,TIME,DATETIME ,IMESTAMP,YEAR

  做用:存儲用戶註冊時間,文章發佈時間,員工入職時間,出生時間,過時時間等

YEAR
            YYYY(範圍:1901/2155)2018

        DATE
            YYYY-MM-DD(範圍:1000-01-01/9999-12-31)例:2018-01-01 

        TIME
            HH:MM:SS(範圍:'-838:59:59'/'838:59:59')例:12:09:32

        DATETIME

            YYYY-MM-DD HH:MM:SS(範圍:1000-01-01 00:00:00/9999-12-31 23:59:59    Y)例: 2018-01-01 12:09:32

        TIMESTAMP

            YYYYMMDD HHMMSS(範圍:1970-01-01 00:00:00/2037 年某時)
year:
    mysql> create table t10(born_year year); #不管year指定何種寬度,最後都默認是year(4)
    mysql> insert into t10 values  
        -> (1900),
        -> (1901),
        -> (2155),
        -> (2156);
    mysql> select * from t10;
    +-----------+
    | born_year |
    +-----------+
    |      0000 |
    |      1901 |
    |      2155 |
    |      0000 |
    +-----------+


date,time,datetime:
    mysql> create table t11(d date,t time,dt datetime);
    mysql> desc t11;
    +-------+----------+------+-----+---------+-------+
    | Field | Type     | Null | Key | Default | Extra |
    +-------+----------+------+-----+---------+-------+
    | d     | date     | YES  |     | NULL    |       |
    | t     | time     | YES  |     | NULL    |       |
    | dt    | datetime | YES  |     | NULL    |       |
    +-------+----------+------+-----+---------+-------+

    mysql> insert into t11 values(now(),now(),now());
    mysql> select * from t11;
    +------------+----------+---------------------+
    | d          | t        | dt                  |
    +------------+----------+---------------------+
    | 2017-07-25 | 16:26:54 | 2017-07-25 16:26:54 |
    +------------+----------+---------------------+



timestamp:
    mysql> create table t12(time timestamp);
    mysql> insert into t12 values();
    mysql> insert into t12 values(null);
    mysql> select * from t12;
    +---------------------+
    | time                |
    +---------------------+
    | 2017-07-25 16:29:17 |
    | 2017-07-25 16:30:01 |
    +---------------------+



============注意啦,注意啦,注意啦===========
    1. 單獨插入時間時,須要以字符串的形式,按照對應的格式插入
    2. 插入年份時,儘可能使用4位值
    3. 插入兩位年份時,<=69,以20開頭,好比50,  結果2050      
                    >=70,以19開頭,好比71,結果1971
    mysql> create table t12(y year);
    mysql> insert into t12 values  
        -> (50),
        -> (71);
    mysql> select * from t12;
    +------+
    | y    |
    +------+
    | 2050 |
    | 1971 |
    +------+



============綜合練習===========
    mysql> create table student(
        -> id int,
        -> name varchar(20),
        -> born_year year,
        -> birth date,
        -> class_time time,
        -> reg_time datetime);

    mysql> insert into student values
        -> (1,'sb1',"1995","1995-11-11","11:11:11","2017-11-11 11:11:11"),
        -> (2,'sb2',"1997","1997-12-12","12:12:12","2017-12-12 12:12:12"),
        -> (3,'sb3',"1998","1998-01-01","13:13:13","2017-01-01 13:13:13");  

    mysql> select * from student;
    +------+------+-----------+------------+------------+---------------------+
    | id   | name | born_year | birth      | class_time | reg_time            |
    +------+------+-----------+------------+------------+---------------------+
    |    1 | sb1 |      1995 | 1995-11-11 | 11:11:11   | 2017-11-11 11:11:11 |
    |    2 | sb2 |      1997 | 1997-12-12 | 12:12:12   | 2017-12-12 12:12:12 |
    |    3 | sb3 |      1998 | 1998-01-01 | 13:13:13   | 2017-01-01 13:13:13 |
    +------+------+-----------+------------+------------+---------------------+

  mysql的日期格式對字符串採用的是'放鬆'政策,能夠以字符串的形式插入。

在實際應用的不少場景中,MySQL的這兩種日期類型都可以知足咱們的須要,存儲精度都爲秒,但在某些狀況下,會展示出他們各自的優劣。下面就來總結一下兩種日期類型的區別。

1.DATETIME的日期範圍是1001——9999年,TIMESTAMP的時間範圍是1970——2038年。

2.DATETIME存儲時間與時區無關,TIMESTAMP存儲時間與時區有關,顯示的值也依賴於時區。在mysql服務器,操做系統以及客戶端鏈接都有時區的設置。

3.DATETIME使用8字節的存儲空間,TIMESTAMP的存儲空間爲4字節。所以,TIMESTAMP比DATETIME的空間利用率更高。

4.DATETIME的默認值爲null;TIMESTAMP的字段默認不爲空(not null),默認值爲當前時間(CURRENT_TIMESTAMP),若是不作特殊處理,而且update語句中沒有指定該列的更新值,則默認更新爲當前時間。

  工做中通常都用datetime就能夠了。 

mysql> create table t1(x datetime not null default now()); # 須要指定傳入空值時默認取當前時間
Query OK, 0 rows affected (0.01 sec)

mysql> create table t2(x timestamp); # 無需任何設置,在傳空值的狀況下自動傳入當前時間
Query OK, 0 rows affected (0.02 sec)

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

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

mysql> select * from t1;
+---------------------+
| x                   |
+---------------------+
| 2018-07-07 01:26:14 |
+---------------------+
1 row in set (0.00 sec)

mysql> select * from t2;
+---------------------+
| x                   |
+---------------------+
| 2018-07-07 01:26:17 |
+---------------------+
1 row in set (0.00 sec)

四 字符串類型

  類型:char,varchar

  做用:名字,信息等等

#官網:https://dev.mysql.com/doc/refman/5.7/en/char.html
#注意:char和varchar括號內的參數指的都是字符的長度

#char類型:定長,簡單粗暴,浪費空間,存取速度快
    字符長度範圍:0-255(一箇中文是一個字符,是utf8編碼的3個字節)
    存儲:
        存儲char類型的值時,會往右填充空格來知足長度
        例如:指定長度爲10,存>10個字符則報錯(嚴格模式下),存<10個字符則用空格填充直到湊夠10個字符存儲

    檢索:
        在檢索或者說查詢時,查出的結果會自動刪除尾部的空格,若是你想看到它補全空格以後的內容,除非咱們打開pad_char_to_full_length SQL模式(SET sql_mode = 'strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH';)

#varchar類型:變長,精準,節省空間,存取速度慢
    字符長度範圍:0-65535(若是大於21845會提示用其餘類型 。mysql行最大限制爲65535字節,字符編碼爲utf-8:https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html)
    存儲:
        varchar類型存儲數據的真實內容,不會用空格填充,若是'ab  ',尾部的空格也會被存起來
        強調:varchar類型會在真實數據前加1-2Bytes的前綴,該前綴用來表示真實數據的bytes字節數(1-2Bytes最大表示65535個數字,正好符合mysql對row的最大字節限制,即已經足夠使用)
        若是真實的數據<255bytes則須要1Bytes的前綴(1Bytes=8bit 2**8最大表示的數字爲255)
        若是真實的數據>255bytes則須要2Bytes的前綴(2Bytes=16bit 2**16最大表示的數字爲65535)
    
    檢索:
        尾部有空格會保存下來,在檢索或者說查詢時,也會正常顯示包含空格在內的內容

  下面咱們來進行一些測試,在測試以前,咱們須要學一下mysql給咱們提供的兩個方法:

    length(字段):查看該字段數據的字節長度

    char_length(字段):查看該字段數據的字符長度

建立一個t1表,包含一個char類型的字段
create table t1(id int,name char(4));
            超過長度:
                嚴格模式下(報錯):
                    mysql> insert into t1 values('xiaoshabi');
                    ERROR 1406 (22001): Data too long for column 'name' at row 1
                非嚴格模式下(警告):
                    mysql> set sql_mode='NO_ENGINE_SUBSTITUTION';
                    Query OK, 0 rows affected (0.00 sec)

                    mysql> create table t1(id int,name char(4));
                    Query OK, 0 rows affected (0.40 sec)

                    mysql> insert into t2 values('xiaoshabi');
                    Query OK, 1 row affected, 1 warning (0.11 sec)
                    查看一下結果:
                    mysql> select * from t1;
                    +------+------+
                    | id   | name |
                    +------+------+
                    |    1 | xiao | #只有一個xiao
                    +------+------+
                    1 row in set (0.00 sec)
                varchar類型和上面的效果是同樣的,嚴格模式下也會報錯。
            
            若是沒有超過長度,那麼char類型時mysql會使用空格來補全本身規定的char(4)的4個字符,varchar不會,咱們來作個對比
            例如:
                #再建立一個含有varchar類型的表t2
                而後插入幾條和t1裏面相同的數據
                mysql>insert into t1 values(2,'a'),(3,'bb'),(4,'ccc'),(5,'d');
                
                mysql>create table t2(id int,name varchar(4));
                
                mysql> insert into t2 values(1,'xiao'),(2,'a'),(3,'bb'),(4,'ccc'),(5,'d');
                查看一下t1表和t2表的內容
                mysql> select * from t1;
                +------+------+
                | id   | name |
                +------+------+
                |    1 | xiao |
                |    2 | a    |
                |    3 | bb   |
                |    4 | ccc  |
                |    5 | d    |
                +------+------+
                5 rows in set (0.00 sec)

                mysql> select * from t2;
                +------+------+
                | id   | name |
                +------+------+
                |    1 | xiao |
                |    2 | a    |
                |    3 | bb   |
                |    4 | ccc  |
                |    5 | d    |
                +------+------+
                5 rows in set (0.00 sec)
                
            好,兩個表裏面數據是同樣的,每一項的數據長度也是同樣的,那麼咱們來驗證一下char的自動空格在後面補全的存儲方式和varchar的不一樣
            
            經過mysql提供的一個char_length()方法來查看一下全部數據的長度
            mysql> select char_length(name) from t1;
            +-------------------+
            | char_length(name) |
            +-------------------+
            |                 4 |
            |                 1 |
            |                 2 |
            |                 3 |
            |                 1 |
            +-------------------+
            5 rows in set (0.00 sec)
            
            mysql> select char_length(name) from t2;
            +-------------------+
            | char_length(name) |
            +-------------------+
            |                 4 |
            |                 1 |
            |                 2 |
            |                 3 |
            |                 1 |
            +-------------------+
            5 rows in set (0.00 sec)
            經過查看結果能夠看到,二者顯示的數據長度是同樣的,不是說好的char會補全嗎,我設置的字段是char(4),那麼長度應該都是4纔對啊?這是由於mysql在你查詢的時候自動幫你把結果裏面的空格去掉了,若是咱們想看到它存儲數據的真實長度,須要設置mysql的模式,經過一個叫作PAD_CHAR_TO_FULL_LENGTH的模式,就能夠看到了,因此咱們把這個模式加到sql_mode裏面:
                mysql> set sql_mode='PAD_CHAR_TO_FULL_LENGTH';
                Query OK, 0 rows affected (0.00 sec)
                
                而後咱們在查看一下t1和t2數據的長度:
                mysql> select char_length(name) from t1;
                +-------------------+
                | char_length(name) |
                +-------------------+
                |                 4 |
                |                 4 |
                |                 4 |
                |                 4 |
                |                 4 |
                +-------------------+
                5 rows in set (0.00 sec)
                
                mysql> select char_length(name) from t2;
                +-------------------+
                | char_length(name) |
                +-------------------+
                |                 4 |
                |                 1 |
                |                 2 |
                |                 3 |
                |                 1 |
                +-------------------+
                5 rows in set (0.00 sec)
                經過結果能夠看到,char類型的數據長度都是4,這下看到了二者的不一樣了吧,至於爲何mysql會這樣搞,咱們後面有解釋的,先看現象就能夠啦。
                
            如今咱們再來看一個問題,就是當你設置的類型爲char的時候,咱們經過where條件來查詢的時候會有一個什麼現象:
                mysql> select * from t1 where name='a';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
            ok,結果沒問題,咱們在where後面的a後面加一下空格再來試試:
                mysql> select * from t1 where name='a ';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
            ok,能查到,再多加一些空格試試,加6個空格,超過了設置的char(4)的4:
                mysql> select * from t1 where name='a      ';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
            ok,也是沒問題的
            總結:經過>,=,>=,<,<=做爲where的查詢條件的時候,char類型字段的查詢是沒問題的。
            可是,當咱們將where後面的比較符號改成like的時候,(like是模糊匹配的意思,咱們前面見過,show variables like '%char%';來查看mysql字符集的時候用過)
                其中%的意思是匹配任意字符(0到多個字符均可以匹配到),還有一個符號是_(匹配1個字符),這兩個字符其實就像咱們學的正則匹配裏面的通配符,那麼咱們經過這些符號進行一下模糊查詢,看一下,char類型進行模糊匹配的時候,是否還能行,看例子:
                mysql> select * from t1 where name like 'a';
                Empty set (0.00 sec)
                發現啥也沒查到,由於char存儲的數據是4個字符長度的,不滿4個是以空格來補全的,你在like後面就只寫了一個'a',是沒法查到的。
                咱們試一下上面的通配符來查詢:
                mysql> select * from t1 where name like 'a%';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
                這樣就能看到查詢結果了
                
                試一下_是否是匹配1個字符:
                mysql> select * from t1 where name like 'a_';
                Empty set (0.00 sec)
                發現一個_果真不行,咱們試試三個_。
                mysql> select * from t1 where name like 'a___';
                +------+------+
                | id   | name |
                +------+------+
                |    2 | a    |
                +------+------+
                1 row in set (0.00 sec)
                發現果真能行,一個_最多匹配1個任意字符。
                若是多寫了幾個_呢?
                mysql> select * from t1 where name like 'a_____';
                Empty set (0.00 sec)
                查不到結果,說明_匹配的是1個字符,但不是0-1個字符。

  測試結果總結:
  針對char類型,mysql在存儲的時候會將不足規定長度的數據使用後面(右邊補全)補充空格的形式進行補全,而後存放到硬盤中,可是在讀取或者使用的時候會自動去掉它給你補全的空格內容,由於這些空格並非咱們本身存儲的數據,因此對咱們使用者來講是無用的。

  char和varchar性能對比:
    以char(5)和varchar(5)來比較,加入我要存三我的名:sb,ssb1,ssbb2
    char:
      優勢:簡單粗暴,無論你是多長的數據,我就按照規定的長度來存,5個5個的存,三我的名就會相似這種存儲:sb ssb1 ssbb2,中間是空格補全,取數據的時候5個5個的取,簡單粗暴速度快
      缺點:貌似浪費空間,而且咱們未來存儲的數據的長度可能會良莠不齊

    varchar:
      varchar類型不定長存儲數據,更爲精簡和節省空間
      例如存上面三我的名的時候相似因而這樣的:sbssb1ssbb2,連着的,若是這樣存,請問這三我的名你還怎麼取出來,你知道取多長能取出第一個嗎?(超哥,我能看出來啊,那我只想說:滾犢子!)
      不知道從哪開始從哪結束,遇到這樣的問題,你會想到怎麼解決呢?還記的嗎?想一想?socket?tcp?struct?把數據長度做爲消息頭。

      
      因此,varchar在存數據的時候,會在每一個數據前面加上一個頭,這個頭是1-2個bytes的數據,這個數據指的是後面跟着的這個數據的長度,1bytes能表示28=256,兩個bytes表示216=65536,能表示0-65535的數字,因此varchar在存儲的時候是這樣的:1bytes+sb+1bytes+ssb1+1bytes+ssbb2,因此存的時候會比較麻煩,致使效率比char慢,取的時候也慢,先拿長度,再取數據。

​       優勢:節省了一些硬盤空間,一個acsii碼的字符用一個bytes長度就能表示,可是也並不必定比char省,看一下官網給出的一個表格對比數據,當你存的數據正好是你規定的字段長度的時候,varchar反而佔用的空間比char要多。

Value CHAR(4) Storage Required VARCHAR(4) Storage Required
'' ' ' 4 bytes '' 1 byte
'ab' 'ab ' 4 bytes 'ab' 3 bytes
'abcd' 'abcd' 4 bytes 'abcd' 5 bytes
'abcdefgh' 'abcd' 4 bytes 'abcd' 5 bytes

        
      缺點:存取速度都慢

  總結:
    因此須要根據業務需求來選擇用哪一種類型來存
    其實在多數的用戶量少的工做場景中char和varchar效率差異不是很大,最起碼給用戶的感知不是很大,而且其實軟件級別的慢遠比不上硬件級別的慢,因此大家公司的運維發現項目慢的時候會加內存、換nb的硬盤,項目的效率提高的會不少,可是咱們做爲專業人士,咱們應該提出來這樣的技術點來提升效率。

    可是對於InnoDB數據表,內部的行存儲格式沒有區分固定長度和可變長度列(全部數據行都使用指向數據列值的頭指針),所以在本質上,使用固定長度的CHAR列不必定比使用可變長度VARCHAR列性能要好。於是,主要的性能因素是數據行使用的存儲總量。因爲CHAR平均佔用的空間多於VARCHAR,所以使用VARCHAR來最小化須要處理的數據行的存儲總量和磁盤I/O是比較好的。

    因此啊,兩個選哪一個均可以,若是是大型併發項目,追求高性能的時候,須要結合大家服務器的硬件環境來進行測試,看一下char和varchar哪一個更好,這也能算一個優化的點吧~~~~

#官網:https://dev.mysql.com/doc/refman/5.7/en/char.html
CHAR 和 VARCHAR 是最常使用的兩種字符串類型。
通常來講
CHAR(N)用來保存固定長度的字符串,對於 CHAR 類型,N 的範圍 爲 0 ~ 255
VARCHAR(N)用來保存變長字符類型,對於 VARCHAR 類型,N 的範圍爲 0 ~ 65 535
CHAR(N)和 VARCHAR(N) 中的 N 都表明字符長度,而非字節長度。
ps:對於 MySQL 4.1 以前的版本,如 MySQL 3.23 和 MySQL 4.0,CHAR(N)和 VARCHAR (N)中的 N 表明字節長度。

#CHAR類型
對於 CHAR 類型的字符串,MySQL 數據庫會自動對存儲列的右邊進行填充(Right Padded)操做,直到字符串達到指定的長度 N。而在讀取該列時,MySQL 數據庫會自動將 填充的字符刪除。有一種狀況例外,那就是顯式地將 SQL_MODE 設置爲 PAD_CHAR_TO_ FULL_LENGTH,例如:
mysql> CREATE TABLE t ( a CHAR(10));
      Query OK, 0 rows affected (0.03 sec)
mysql> INSERT INTO t SELECT 'abc';
      Query OK, 1 row affected (0.03 sec)
      Records: 1  Duplicates: 0  Warnings: 0
mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G;
      *************************** 1. row ***************************
              a: abc
         HEX(a): 616263
      LENGTH (a): 3
      1 row in set (0.00 sec)
      mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
      Query OK, 0 rows affected (0.00 sec)
mysql> SELECT a,HEX(a),LENGTH(a) FROM t\G;
      *************************** 1. row ***************************
              a: abc
         HEX(a): 61626320202020202020
      LENGTH (a): 10
      1 row in set (0.00 sec)

在上述這個例子中,先建立了一張表 t,a 列的類型爲 CHAR(10)。而後經過 INSERT語句插入值「abc」,由於 a 列的類型爲 CHAR 型,因此會自動在後面填充空字符串,使其長 度爲 10。接下來在經過 SELECT 語句取出數據時會將 a 列右填充的空字符移除,從而獲得 值「abc」。經過 LENGTH 函數看到 a 列的字符長度爲 3 而非 10。
接着咱們將 SQL_MODE 顯式地設置爲 PAD_CHAR_TO_FULL_LENGTH。這時再經過 SELECT 語句進行查詢時,獲得的結果是「abc 」,abc 右邊有 7 個填充字符 0x20,並通 過 HEX 函數獲得了驗證。此次 LENGTH 函數返回的長度爲 10。須要注意的是,LENGTH 函數返回的是字節長度,而不是字符長度。對於多字節字符集,CHAR(N)長度的列最多 可佔用的字節數爲該字符集單字符最大佔用字節數 *N。例如,對於 utf8 下,CHAR(10)最 多可能佔用 30 個字節。經過對多字節字符串使用 CHAR_LENGTH 函數和 LENGTH 函數, 能夠發現二者的不一樣,示例以下:
mysql> SET NAMES gbk;
     Query OK, 0 rows affected (0.03 sec)
mysql> SELECT @a:='MySQL 技術內幕 '; Query OK, 0 rows affected (0.03 sec)
mysql> SELECT @a,HEX(@a),LENGTH(@a),CHAR_LENGTH(@a)\G; ***************************** 1. row **************************** a: MySQL 技術內幕
HEX(a): 4D7953514CBCBCCAF5C4DAC4BB
LENGTH (a): 13
CHAR_LENGTH(a): 9
1 row in set (0.00 sec)

變 量 @ a 是 g b k 字 符 集 的 字 符 串 類 型 , 值 爲 「 M y S Q L 技 術 內 幕 」, 十 六 進 制 爲 0x4D7953514CBCBCCAF5C4DAC4BB,LENGTH 函數返回 13,即該字符串佔用 13 字節, 由於 gbk 字符集中的中文字符佔用兩個字節,所以一共佔用 13 字節。CHAR_LENGTH 函數 返回 9,很顯然該字符長度爲 9。



#VARCHAR類型
VARCHAR 類型存儲變長字段的字符類型,與 CHAR 類型不一樣的是,其存儲時須要在 前綴長度列表加上實際存儲的字符,該字符佔用 1 ~ 2 字節的空間。當存儲的字符串長度小 於 255 字節時,其須要 1 字節的空間,當大於 255 字節時,須要 2 字節的空間。因此,對 於單字節的 latin1 來講,CHAR(10)和 VARCHAR(10)最大佔用的存儲空間是不一樣的, CHAR(10)佔用 10 個字節這是毫無疑問的,而 VARCHAR(10)的最大佔用空間數是 11 字節,由於其須要 1 字節來存放字符長度。
-------------------------------------------------
注意 對於有些多字節的字符集類型,其 CHAR 和 VARCHAR 在存儲方法上是同樣的,一樣 須要爲長度列表加上字符串的值。對於 GBK 和 UTF-8 這些字符類型,其有些字符是以 1 字節 存放的,有些字符是按 2 或 3 字節存放的,所以一樣須要 1 ~ 2 字節的空間來存儲字符的長 度。
-------------------------------------------------
雖然 CHAR 和 VARCHAR 的存儲方式不太相同,可是對於兩個字符串的比較,都只比 較其值,忽略 CHAR 值存在的右填充,即便將 SQL _MODE 設置爲 PAD_CHAR_TO_FULL_ LENGTH 也同樣,例如:
mysql> CREATE TABLE t ( a CHAR(10), b VARCHAR(10));
    Query OK, 0 rows affected (0.01 sec)
mysql> INSERT INTO t SELECT 'a','a';
    Query OK, 1 row affected (0.00 sec)
    Records: 1  Duplicates: 0  Warnings: 0
mysql> SELECT a=b FROM t\G;
    *************************** 1. row ***************************
    a=b: 1
    1 row in set (0.00 sec)
    mysql> SET SQL_MODE='PAD_CHAR_TO_FULL_LENGTH';
    Query OK, 0 rows affected (0.00 sec)
mysql> SELECT a=b FROM t\G;
    *************************** 1. row ***************************
    a=b: 1
    1 row in set (0.00 sec)

  其餘的字符串類型:BINARY、VARBINARY、BLOB、TEXT

  img

BINARY 和 VARBINARY 相似於 CHAR 和 VARCHAR,不一樣的是它們包含二進制字符串而不要非二進制字符串。也就是說,它們包含字節字符串而不是字符字符串。這說明它們沒有字符集,而且排序和比較基於列值字節的數值值。
BLOB 是一個二進制大對象,能夠容納可變數量的數據。有 4 種 BLOB 類型:TINYBLOB、BLOB、MEDIUMBLOB 和 LONGBLOB。它們區別在於可容納存儲範圍不一樣。
有 4 種 TEXT 類型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。對應的這 4 種 BLOB 類型,可存儲的最大長度不一樣,可根據實際狀況選擇。

BLOB:
     1._BLOB和_text存儲方式不一樣,_TEXT以文本方式存儲,英文存儲區分大小寫,而_Blob是以二進制方式存儲,不分大小寫。
     2._BLOB存儲的數據只能總體讀出。
     3._TEXT能夠指定字符集,_BLO不用指定字符集。

五 枚舉類型與集合類型

  字段的值只能在給定範圍中選擇,如單選框,多選框,若是你在應用程序或者前端不作選項限制,在MySQL的字段裏面也能作限制
  enum 單選 只能在給定的範圍內選一個值,如性別 sex 男male/女female
  set 多選 在給定的範圍內能夠選擇一個或一個以上的值(愛好1,愛好2,愛好3...)

枚舉類型(enum)
            An ENUM column can have a maximum of 65,535 distinct elements. (The practical limit is less than 3000.)
            示例:
                CREATE TABLE shirts (
                    name VARCHAR(40),
                    size ENUM('x-small', 'small', 'medium', 'large', 'x-large')
                );
                INSERT INTO shirts (name, size) VALUES ('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small');

  

          集合類型(set)
            A SET column can have a maximum of 64 distinct members.
            示例:
                CREATE TABLE myset (col SET('a', 'b', 'c', 'd'));
                INSERT INTO myset (col) VALUES ('a,d'), ('d,a'), ('a,d,a'), ('a,d,d'), ('d,a,d');
mysql> create table consumer( 
    -> name varchar(50),
    -> sex enum('male','female'),
    -> level enum('vip1','vip2','vip3','vip4','vip5'), #在指定範圍內,多選一
    -> hobby set('play','music','read','study') #在指定範圍內,多選多
    -> );

    mysql> insert into consumer values  
        -> ('xiaogui','male','vip5','read,study'),
        -> ('taibai','female','vip1','girl');

    mysql> select * from consumer;
    +------+--------+-------+------------+
    | name | sex    | level | hobby      |
    +------+--------+-------+------------+
    | xiaogui | male   | vip5  | read,study |
    | taibai | female | vip1  |            |
    +------+--------+-------+------------+
相關文章
相關標籤/搜索