MySQL(二) 資料庫資料型別詳解

一杯涼茶發表於2016-12-08

      序言

         今天去健身了,感覺把身體練好還是不錯的,閒話不多說,把這個資料庫所遇到的資料型別今天統統在這裡講清楚了,以後在看到什麼資料型別,我們度應該認識,對我來說,最不熟悉的應該就是時間型別這塊了。但是通過今天的學習,已經解惑了。下面就跟著我的節奏去把這個拿下吧。

                                          ---WH

 

一、資料型別

        MySQL的資料型別有大概可以分為5種,分別是 整數型別浮點數型別和定點數型別日期和時間型別字串型別二進位制型別。現在可以來看看你對這5種型別的熟悉程度,哪個看起來懵逼了,那就說明自己哪個不熟悉,不理解。  

        注意:整數型別和浮點數型別可以統稱為數值資料型別,這不難理解。

        數值資料型別

          整數型別:TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT

          浮點數型別:FLOAT、DOUBLE

          定點小數:DECIMAL

        日期/時間型別

          YEAR、TIME、DATE、DATETIME、TIMESTAMP

        字串型別

          CHAR、VARCHAR、TEXT、ENUM、SET等   

        二進位制型別

          BIT、BINARY、VARBINARY、BLOB

 

      1、整數型別

                

          不管你學什麼語言,在基礎方面,都應該知道  1個位元組= 8位二進位制數。 每個型別的取值範圍也就能夠知道,比如 TINYINT佔用1個位元組,也就是8位,2的8次方減1等於255,也就是說如果代表沒符號的整數,該取值範圍為0~255,如果是有符號的,最高位為符號號位,也就是2的7次方減1,也就是127,取值範圍為-128~127, 為什麼需要減1,這個問題就需要考慮臨界值的問題了。而考慮臨界值問題又有需要討論原碼補碼反碼的知識,這些度不是我們討論的重點,所以在這就自行百度。給出一張範圍表,給大家做參考。

 

                不同整數型別的取值範圍

          

      根據自己所需去選取不同的型別名稱,

      例如:

         CREATE TABLE aaa(

            id INT(10) PRIMARY KEY,

            age INT(6)

         );

      這個例子中INT(10)、INT(6) 括號中的數字表示的是該資料型別指定的顯示寬度,指定能夠顯示的數值中數字的個數。這裡要注意:顯示寬度和資料型別的取值範圍是無關的,顯示寬度只是指明MySQL最大可能顯示的數字個數,注意是可能。通俗點講就是,比如這個age欄位,顯示寬度為6,但是如果你插入的資料大於6,達到了8,6666 6666,那也沒關係,只要插入的數值的位數不超過該型別整數的取值範圍,就行,如果插入的數值長度是4,或者3,數值的位數小於指定的寬度,後面的位數就會由空格填空,5555插入age欄位,存的就是"5555  "後面用空格補齊。還有一點,這個顯示寬度沒限制,你寫100度沒問題,但是插入資料時,實際起控制作用的還是資料型別的取值範圍。如果不寫顯示寬度,就會用系統預設的,比如,INT的預設顯示寬度是11,看上面表,最高也就能表示10位大小的數值,但是要注意,有符號的,也就是負數時,符號位也佔一位。

 

      2、浮點數型別和定點數型別

            

       2.1解釋M,D的意思:

              M:數值的總位數。 通俗點講,就是看有多少個數字,比如,5.6789,M就是5

              D:小數點後面能保留幾位。 比如上面的5.6789 ,D就是4。 這只是舉一個例子,來說明M,D是什麼,實際是先有M,D的,然後在來控制數值,而不是更具數值來確定M,D。

          不單單就MECIMAL有M,D這兩個引數,FLOAT 和 DOUBLE 度有,看下面例子

         比如:

           CREATE TABLE tmp(

              x FLOAT(3,1),

              y DOUBLE(5,3),

              z DECIMAL(5,4)

           );

           假設x插入的值為:5.69,56.78,5.438,349.2 (注意:實驗給x這個欄位插入的值,可能實驗了三次,不要錯看成x的值為5.69,y為56.78等等了)

           實際上在資料庫中存的值為:5.7,56.9,5.3,349.2這個報錯

           分析:x的M為3,D為1,那麼小數點上必須是佔了一位數字,就算沒有值,也會用0來填充,所以說,整數位上最多就只能是2位,這裡要切記要先根據D的值,來算整數位能最多有多少位。

           通過分析x,y和z也就簡單了,

            y欄位上的值,整數部分最多是2位,小數點後的位數最多是3位,也就是說小數點後超過了3位,就會四捨五入。

            z欄位上的值,整數部分最多隻能是一位,小數點後的位數最多是4位,如果不足4位,也會用0補充。比如插入1.56,在資料庫中存的就是1.5600, 比如插入25.46,這個就會報錯,因為整數部分只能是一位,小數點後的位數已經佔了4位了。這裡要搞清楚。

 

         2.2、FLOAT、DOUBLE、DECIMAL三者的區別。

            都是用來表示我們所說的小數的也就是浮點數,但是三種的精度不一樣,也就是後面顯示的位數不一樣,

              區別一:

                FLOAT顯示後面的小數點位大概在40多位,

                DOUBLE能顯示的就是300多位了,不是一個層次上的,

                DECIMAL這個小數點後面能顯示的位數跟DOUBLE差不多,

              區別二:

                 FLOAT和DOUBLE在不指定精度時,也就是不用(M,D),預設會按照實際的精度,也就是你寫多少就是多少,而DECIMAL如不指定精度預設為(10,0),也就是如果不指定精度,插入數值56.89,在資料庫中儲存的就是57。所以一般使用DECIMAL時就會指定精度,而使用FLOAT和DOUBLE就不用。

              區別三:

                 浮點數相對與定點數(DECIMAL)的優點就是在長度一定的情況下,浮點數能夠表示更大的資料範圍,但是缺點是會引起精度問題。

 

         2.3、什麼時候使用FLOAT、DOUBLE、DECIMAL

            對精度要求比較高的時候,比如貨幣、科學資料等,使用DECIMAL的型別比較好。其他的時候,看你要存放的資料的大小而定了,一般使用DOUBLE。並且在使用浮點數時需要注意,儘量避免做浮點數的比較,比如加、減,誰大誰小,這樣的操作,會引起精度缺失。相信在一些程式語言中,遇到過float精度丟失的問題。

    

 

    3、日期與時間型別

            

         現在有些東西看不懂沒關係,大概有個瞭解先,接下來一一進行講解。

       3.1、YEAR 

           3.1.1、重點看他的儲存範圍,1901~2155. 在插入該數值時,有兩種方式,一種是用字串來代表插入的YEAR值,另一種是用數字代表YEAR值,其中字串插入的可以用單引號和雙引號,沒區別,跟一些程式設計語言不一樣,單個字元就必須用單引號,多字元就要用雙引號,在MySQL中,單雙引號度表示字元。

             例子:

              CREATE TABLE tmp(

                y YEAR

              );     

             向表中插入資料:INSERT INTO tmp VALUES(2010),('2010'),("2010");

             查詢表中資料:SELECT * FROM tmp;

             能檢視三條記錄度插入到資料庫tmp表中了。注意:這裡插入資料和查詢資料操作還沒學過,如果不知道,可以暫時跳過,直接看結論。

                        

 

             如果向表中插入超出範圍的值,2166則會報錯

                       

          3.1.2、在插入完整年份時,用字串和用數字代表YEAR值的效果是一樣的,但是當省略YEAR值時,用這兩種方式就不一樣了。

              例子一:就拿上面那張tmp表來說。向表中插入用字串代表的YEAR值,'’0' 、'00'、 '77'、 '10'

                刪除表中資料:DELETE FROM tmp;

                向表中插入資料:INSERT INTO tmp VALUES('0'),('00'),('77'),('10');

                       

               結果:

                  插入的字元'0'、'00'變成了2000

                  插入的字元'77'變成了1977

                  插入的字元'10'變成了2010

 

             例子二:向tmp表中y欄位插入2位數字表示YEAR值,0,00,78,11

                刪除表中資料:DELETE FROM tmp;

                向表中插入資料:INSERT INTO tmp VALUES(0),(00),(77),(11);

                       

                結果:

                   插入的數字0、00變成了0000

                   插入的數字77變成了1977

                   插入的數字11變成了2011

        

            結論:在省略寫年份時,

               1、用字元表示和用數字表示的區別就在於0。如果是字元0或字元00,則在資料庫中會生成2000,如果是數字0或00,則會生成0000. 

               2、在不超過70,也就是小於70,度會生成2000年以上,也就是如果是69,則生成2069.如果是70以上包含70,就會變成1970以上。比如70,就會變為1970。也就是00-69範圍的年值轉換為2000~2069. 70-99範圍的年值轉換為1970~1999

               3、一般我們如果要使用,也就用全稱,這樣不容易混淆,但是得知道有這些特性

 

 

       3.2、TIME       

          格式:HH:MM:SS   HH表示小時 、MM表示分鐘、SS表示秒

          取值範圍:-838:59:59 ~ 838:59:59

          解釋:這裡的時間不僅僅可以用來表示一天的時間(也就是24小時),還可能是某件事情過去的時間或兩個事件之間的時間間隔,通俗點講,我們平常每天的時間就是從凌晨0點就重新開始計時,計滿24個小時,然後又重新開始,也就相當於當前我們看到的時間是凌晨0點過去的時間,也就是距凌晨0點過去了多少個小時。 早上7點,也就是距離凌晨0點這件事7個小時,以此類推,直到距離了24個小時,然後重新開始計算。 在MySQL中,這個TIME就不侷限於每天距離凌晨0點多長時間了,可以是過去某個時間距離現在多長時間了,比如昨天早上7點,距離現在上午9.00多長時間了,就超過了24小時,所以。這個TIME的取值範圍就比我們所理解的24小時更大。

          3.2.1、表示TIME有很多種格式,上面的HH:MM:SS只是標準的一種,

            1、D HH:MM:SS :D表示日、天數。在資料庫中儲存時,D會被轉換為小時儲存,D*24+HH

            2、HH:MM 、D:HH、 SS  :這些格式度是可以的,注意最後一個,如果是單獨就是2個數字,那麼就代表的是秒,比如"20"那就代表的是00:00:20 

            3、HHMMSS: 這是沒有間隔符的字串或者數值,比如101112會被理解為10:11:12,但是109712就是不合法的,因為分鐘位上超過了59。儲存時會報錯。這個沒有冒號時需要注意一點,數值的最右邊兩位表示秒,以此類推,比如 5523 表示的是00:55:23而不是55:23:00。 所以說上面SS格式時代表的是秒就是這樣來的,從最右邊看起。如果有冒號,則從左邊小時開始看起,比如 55:23 就是代表的55:23:00 

          例如:

            CREATE TABLE tmp(

              t TIME

            );

            插入值"10:05:05"、"23:23"、"2 10:10"、"3 02"、"10"、"101112"、"109712"

            INSERT INTO tmp VALUES("10:05:05"),("23:23"),("2 10:10"),("3 02"),("10"),("101112");

            SELECT * FROM tmp;  

                      

            可以看出:都是如我們預期的那樣顯示資料。  

          3.2.2、使用系統的函式,插入當前的時間。

            DELETE FROM tmp;

            INSERT INTO tmp VALUES(CURRENT_TIME),(NOW());

            SELECT * FROM tmp;

                     

            

        3.3、DATE

            格式:YYYY-MM-DD  YYYY表示年份  MM表示月份  DD表示日

            取值範圍:1000-01-01~9999-12-3

              使用字元或者數值的資料度可以插入

            注意:這個除了標準格式之外,跟TIME一樣YEAR一樣,在年份這裡也有其省略格式,其規則和YEAR中一樣。00-69範圍的年值轉換為2000~2069. 70-99範圍的年值轉換為1970~1999。  例如:12-12-31 表示2012-12-31  981231表示1998-12-31

            也可以使用CURRENT_DATE或者NOW()插入當前的系統日期。

            例子:(注意,每次建立表之前,會把之前的老表給刪除掉,這裡省略掉了,使用DROP TABLE 表名; )

               CREATE TABLE tmp(

                 d DATE

               );

               INSERT INTO tmp VALUES("1998-08-08"),(19980808),(100511),(CURRENT_DATE),(NOW());

               SELECT * FROM tmp;

                      

 

            注意:MySQL允許“不嚴格”語法,也就是任何標點符號度可以當用日期部分之間的間隔符,比如"98.11.23"、"98/11/31"、"98@11@31"都可以,自己可以去嘗試嘗試,但是一般使用標準格式比較好,讓人看起來舒服。

 

        3.4、DATETIME  

            格式:YYYY-MM-DD HH:MM:SS 

            取值範圍:1000-01-01 00:00:00~9999-12-3 23:59:59

                  這個不用做多解釋,因為這個就是DATE和TIME的結合體。其各種特點在這裡也能夠適合。但是注意HH:MM:SS 只能表示一天的時間,也就最多到23:59:59.

            例子:

               CREATE TABLE tmp(

                 dt DATETIME

               );        

               INSERT INTO tmp VALUES("1998-08-08 08-08-08"),(980808080808),(CURRENT_DATE()),(NOW());

               SELECT * FROM tmp;

                      

 

             CURRENT_DATE()返回的是當前系統的日期 格式 YYYY-MM-DD 所以在前面列印YEAR和DATE度可以用到該函式,因為包含了其資料型別所要的資訊

             NOE()返回當前系統的日期和時間值,格式為YYYY-MM-DD HH:MM:SS,所以在這裡能夠使用其輸出DATETIME型別的值。

 

        3.5、TIMESTAMP

             格式:YYYY-MM-DD HH:MM:SS

             取值範圍:1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:17 UTC

             解釋:顯示寬度固定在 19個字元。也就是這個輸出標準格式,UTC表示世界標準時間,這個跟DATETIME基本上一樣,但是有一個最大的區別,我們需要知道。

             區別:儲存位元組和支援的範圍不一樣,最重要的區別在DATETIME在儲存日期資料時,按實際輸入的格式儲存,即輸入什麼就儲存什麼,也就輸出什麼,與時區無關,而TIMESTAMP值的儲存是以UTC格式儲存,儲存時會對當前時區進行轉換,檢索時再轉換回當前時區,也就是查詢時,會根據當前時區的不同,顯示的時間值不同。 時區的意思就是,你在美國和你在中國兩邊的時間顯示不一樣,你在美國有在美國的時間,比中國快多長時間,比如在中國才早上8點,在美國可能就是晚上8.9點了(這個只是打個比方,準備轉換時間我沒去看。)

             例如:

              CREATE TABLE tmp(

                ts TIMESTAMP

              );

              INSERT INTO tmp VALUES(NOW());

              SELECT * FROM tmp;

                      

              轉換時區

                      

              可以看到,如我們所想,輸出時間變了,增加了兩個小時,這個是關於什麼東10區,東8區等,我也不懂這些時差,總之能夠得出結論就行了。

              也就是說,TIMESTAMP和DATETIME其實差不多,就是一個時區的差別。TIMESTAMP也叫時間戳。以後遇到它我們就應該知道是什麼東西了

 

    4、字串型別

         有CHAR、CARCHAR、TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT、ENUM、SET

                    

         4.1、CHAR和VARCHAR

            CHAR(M):為固定長度字串,固定長度的意思就是M的值為多少,那麼該M的值就是其實際儲存空間的值,就算插入的資料少於M位,其儲存空間還是那麼大,多餘的用空格補齊。在輸出時,空格將被刪除不輸出。M最大為255,比如char(4),如果插入abc,則儲存的值為'abc '後面多了一個空格,輸出還是‘abc’, 儲存空間還是佔4個位元組。M最大為255

            VARCHAR(M):長度可變的字串,跟CHAR相反,會根據實際的大小值來確定儲存空間的大小,比如 VARCHAR(4),插入'ab',則儲存空間為3位元組,看上面圖就知道VARCHAR會多一個位元組用來儲存長度,M最大為65535.

            注意:字串跟數值型別不一樣,M為多大,就最多能插入多少字元,超過了M,就會報錯

            例子:

              CREATE TABLE tmp(

                ch CHAR(4),

                vch VARCHAR(4);

              );          

              INSERT INTO tmp VALUES('asdf','asdfg');

              結果報錯:

                      

              INSERT INTO tmp VALUES('ab  ','ab  ');

              SELECT concat( '(', ch ,')' ),concat( '(',vch,')' ) FROM tmp;//這句話的意思就用(將結果包起來,用來觀察輸出的字元長度)

                        

              說明,CHAR不能夠儲存空格字元,而VARCHAR可以。        

      

          4.2、TEXT

              text分四種:TINYTEXT、TEXT、MEDIUMTEXT和LONGTEXT

                TINYTEXT:255字元

                TEXT:65535字元

                MEDIUNTEXT:16777215字元

                LONGTEXT:4294967295,大概4GB的字元

              也就是說,比如我們要存一本小說,那麼就需要使用上面四種中的一種來儲存,選取MEDIUNTEXT或者LONGTEXT差不多。

 

          4.3、ENUM

              列舉,格式:欄位名 ENUM('值1','值2','值3'...,'值n');  n最多為65535

              例如:

                CREATE TABLE tmp(

                  enm ENUM('first','second','third');

                );      

                解釋:enm欄位的資料型別為ENUM,列舉型別,那麼在插入該欄位中的值只能為列舉中的這幾個值,不能插入別得值,否則報錯

                INSERT INTO tmp VALUES('first'),('FIRST');

                SELECT * FROM tmp;

                        

                  MySQL不區分大小寫。

                  INSERT INTO tmp VALUES('four');

                  報錯:

                        

                例子二:

                  CREATE TABLE tmp(

                    soc INT,

                    level ENUM('excellent','good','bad')

                  );

                  INSERT INTO tmp VALUES(70,2),(90,1),(55,3);

                  SELECT * FROM tmp;

                        

                  使用索引值,也可以選擇列舉中得值,從1開始,不是0,注意這點

 

                總結:使用ENUM型別就是為了限制欄位上的值的取值範圍,只能取我們所規定的值。

 

            4.4、SET

                格式:欄位名 SET('值1','值2','值3','值4'...,'值n')  n最大為64

                通過例子來講解這個SET的特點

                  CREATE TABLE tmp(

                    s SET('a','b','c','d');

                  );

                  INSERT INTO tmp VALUES('a'),('a,b,a'),('c,a,d');

                  SELECT * FROM tmp;

                        

                   a 變成 a

                   a,b,a 變成 a,b

                   c,a,d 變成 a,c,d

                   結論:

                      1、插入SET欄位中的值如果有重複,則會自動刪除重複的值

                      2、插入SET欄位中的值會按順序排列,排列規則就是按照SET中的值的排列優先順序

                   INSERT INTO tmp VALUES('a,x,b');

                   報錯:

                        

                   結論:

                      3、如果插入了不屬於SET中的值,就會報錯

                   SET的特性就上面所說的三點   

 

      5、二進位制型別  

           用來存放二進位制數,也就是01010這種。有BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUNBLOB和LONGBLOB

                       

           5.1、BIT型別 

                位欄位型別,M表示插入值的位數,最大為64位,預設值為1,如果插入值小於M位,值的左邊用0填充,

                例子:

                   CREATE TABLE tmp(

                      b BIT(4)

                   );   

                   解釋:4位的二進位制,也就是能夠儲存0到15之間的值。

                   INSERT INTO tmp VALUES(2),(10),(15);       

                   SELECT BIN(b+0) FROM tmp;

                         

                   解釋:我們將2,10,15這三個10進位制存入資料表中,其欄位為BIT型別,所以在表中存放的是二進位制數,但是將其顯示出來,要先將二進位制數轉換為對應的數字的值,也就是通過b+0, 然後在通過BIN()函式將數字轉換為二進位制。我們可以嘗試不用BIN()函式,只用b+0,看輸出什麼

                   SELECT b+0 FROM tmp;

                          

 

            5.2、BINARY和VARBINARY型別

                  格式:欄位 BINARY(M)或者VARBINARY(M)

                  這兩個跟CHAR和VARCHAR類似,

                    BINARY:長度是固定的,指定長度後,不足最大程度的,將在它們右邊填充"\0"來達到指定長度,

                    VARBINARY:長度是可變的,制定好長度後,其長度可以在0到最大值之間,例如,指定欄位資料型別為VARBINARY(20),如果插入的值的長度只有10,則實際儲存空間為10加1,即實際佔用的空間為字串的實際長度加1.

                  說了這麼多,但是還是不明白這兩個有什麼用處,現在來告訴你,我們說MySQL中對大小寫不敏感,但是這兩個資料型別卻對大小寫敏感,原因是他們是用二進位制來儲存資料的,比如A和a,兩個的二進位制就不一樣。所以在很多時候我們需要區分大小寫的時候,就會用到該型別。

                  注意:這兩個型別的長度計算的是位元組長度,一個字元等於2個位元組,比如BINARY(4)這個表示能夠存放4個位元組的長度,也就是隻能存放2個漢字。可以存4個字母。不要把這個長度當成二進位制位的長度了,說是二進位制字串的意思是,用二進位制來進行儲存,但是其長度約束是位元組長度。

                  例子:

                    CREATE TABLE tmp(

                      b BINARY(10)

                    );

                    INSERT INTO tmp VALUES('a');

                    select * from tmp WHERE b='A';

                          

                    解釋:在tmp表中存放了一個小寫a,然後通過大寫A查詢表中,看是否能找到a,結果找不到,就驗證了我們上面的說法,具有區分大小寫的功能。

 

                總結:BINARY和VARBINARY的主要作用就是用來區分大小寫的,其他沒什麼作用,但是使用時要注意限制其大小的是位元組數,而不是二進位制位,它儲存的格式是用二進位制來儲存的。這兩個不要搞混淆了。

 

 

          5.3、BLOB型別

                是一個二進位制大物件,TINYBLOB(32kb)、BLOB(64kb)、MEDIUMBLOB(16M)和LONGBLOB(4GB)。一般儲存的是一些影象,音訊檔案。

 

 

 

二、如何選擇資料型別             

        1、整數和浮點數

          如果不需要小數部分,則使用整數來儲存資料,並且根據整數的大小,來選擇合適的整數型別,如果需要小數部分,則使用浮點數型別,浮點數型別中,有float和double,如果需要精度高一點,則選擇double。根據自己的需求來決定選什麼。

        2、浮點數和定點數

          浮點數FLOAT、DOUBLE相對應定點數DECIMAL的優勢在於:在長度一定的情況下,浮點數能表示更大的資料範圍,但是浮點數容易產生誤差,因此在精度比較高時,建議使用DECIMAL,比如貨幣這一類東西,就用DECIMAL比較合理,注意浮點數在進行加減運算時也容易出現問題。如果進行數值比較,也建議用DECIMAL

        3、日期與時間型別

          可以看上面詳解時的圖,根據各種格式,選擇自己所需要的資料型別,注意TIMESTAMP和DATETIME的區別,一個是跟時區有關,一個無關,其他沒什麼大的區別。

        4、CHAR與VARCHAR之間的特點與選擇

          區別:

            CHAR是固定長度字元、VARCHAR是可變長度字元。CHAR會自動刪除插入資料的尾部空格,VARCHAR不會。 

            CHAR是固定長度,處理速度比VARCHAR更快,缺點很明顯,浪費儲存空間,所以對儲存不大,但在速度上有要求的可以使用CHAR型別,反之用VARCHAR。

        5、ENUM和SET

           ENUM只能取單值,也就是從列舉型別中選取其中一個值,但是SET可以取多值,

           ENUM最多能存放65535個成員,SET只能65個

           空字串也能在SET中儲存,

           要儲存一個人的喜愛時,最好使用SET型別,其實最重要的是看具體的情況在選取最為合適的把

        6、BLOB和TEXT

           BLOB是二進位制字串,TEXT是非二進位制字串,兩者均可存放大容量的資訊,BLOB主要儲存圖片、音訊資訊,而TEXT只能儲存純文字檔案。分清楚兩者的用途

 

        7、BINARY和VARBINARY

           這兩個的區別和CHAR與VARCHAR的區別差不多,BINARY是固定長度、VARBINARY是可變程度,這兩個的作用就是為了區分大小寫的,注意這兩個是位元組字串。

 

 

  

     

 

相關文章