MySQL基礎數據類型

来源:https://www.cnblogs.com/changxin7/archive/2019/09/16/11528101.html
-Advertisement-
Play Games

一 介紹 存儲引擎決定了表的類型,而表記憶體放的數據也要有不同的類型,每種數據類型都有自己的寬度,但寬度是可選的 詳細參考: http://www.runoob.com/mysql/mysql data types.html http://dev.mysql.com/doc/refman/5.7/en ...


一 介紹

  存儲引擎決定了表的類型,而表記憶體放的數據也要有不同的類型,每種數據類型都有自己的寬度,但寬度是可選的

  詳細參考:

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

  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. 枚舉類型與集合類型

二 數值類型

  1、整數類型

    整數類型: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  

    無符號最大值為:4294967296-1

    有符號最大值:2147483648-1

    有符號和無符號的最大數字需要的顯示寬度均為10,而針對有符號的最小值則需要11位才能顯示完全,所以int類型預設的顯示寬度為11是非常合理的

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

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

  2、浮點型

    定點數類型 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)

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

    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  |            |
    +------+--------+-------+------------+

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我們在虛擬機中安裝好centos後,需要手動配置網卡,得到IP。可以先配置臨時IP,然後在遠程連接軟體中配置永久IP。 ...
  • 大多數人都厭煩使用老舊的系統,無論軟體還是硬體。但有的時候又不得不困守其中,堅持延續著系統的壽命,或者還需要點幾柱香,祈求神佛的護佑。 Linux是一個模塊化極好的操作系統,得益於此,當其中有組件落伍之時,大多數情況下,還能通過下載源碼,手工編譯來升級組件,從而保證系統的可用性。 在這個過程中,cU ...
  • 配置Linux使用LDAP用戶認證 本文首發:https://www.cnblogs.com/somata/p/LinuxLDAPUserAuthentication.html 我這裡使用的是CentOS完成的LDAP用戶管理,可能與網上的大部分教程不同,不過寫出來了,那麼是肯定能用的了,不過會有部 ...
  • 準備工作 Ubuntu 獲取地址: "官網" "清華鏡像站" VMware 獲取地址 "鏈接" 安裝過程 Vmware的安裝過程此處不在贅述,不清楚如何安裝的請自行百度,參見 "VMware14安裝教程" 然後就是Vmware中安裝Ubuntu18.04的過程如下: 總結 至此,Ubuntu18.0 ...
  • 建一個Maven項目, pom裡加下jedis依賴, 1 2 3 4 5 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependenc ...
  • altrun:http://xbeta.info/altrun.htm timer:https://www.playpcesor.com/2009/04/timer.html (好像要上網打開) doit.im :時間管理軟體 ...
  • // 當時我裝這個也是折騰了一下午 , 所以寫一個筆記記錄一下; //如果哪裡有問題的話我們可以一起討論( qq: 2970911340,郵箱[email protected]),這也是我第一次寫博客 練練手 1. 安cmake工具 # yum install -y cmake 2. 創建mysql用戶 #usera ...
  • 講redolog和binlog之前,先要講一下一條mysql語句的執行過程。 1、client的寫請求到達連接器,連接器負責管理連接、驗證許可權; 2、然後是分析器,負責複習語法,如果這條語句有執行過,在緩存內,那麼就從緩存去寫; 3、緩存沒有的話,那就到了優化器部分。負責優化sql讀寫,選擇索引; ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...