1. 程式人生 > >MySQL學習之路5

MySQL學習之路5

資料型別和運算子

1 . MySQL資料型別介紹
MySQL主要支援的資料型別有:數值型別、日期/時間型別、字串型別。
(1)數值資料型別:包括整數型別TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT、浮點小數資料型別FLOAT和DOUBLE、定點小數型別DECIMAL。
(2)日期/時間型別:包括YEAR、TIME、DATE、DATETIME和TIMESTAMP。
(3)字串型別:包括CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET等。

1.1 整數型別
整數型別的屬性欄位可以新增AUTO_INCREMENT自增約束條件。
MySQL中的整數型資料型別:

型別名稱 說明 儲存需求
TINYINT 很小的整數 1個位元組(8 bits)
SMALLINT 小的整數 2個位元組
MEDIUMINT 中等大小的整數 3個位元組
INT(INTEGER)INT 普通大小的整數 4個位元組
BIGINT 大整數 8個位元組
TINYINT需要1個位元組(8 bits)來儲存,那麼TINYINT無符號數的最大值為2^8 - 1,即255; TINYINT無符號數的最大值為2^7 - 1,即127;

不同整數型別的取值範圍

資料型別 有符號 無符號
TINYINT -128~127 0~255
SMALLINT -32768~32767 0~65535
MEDIUMINT -8388608~8388607 0~16777215
INT(INTEGER)INT -2147483648~2147482617 0~4294967295
BIGINT -9223372036854775808~9223372036854775807 0~18446744073709551615

下面你需要注意的地方是:如INT(11)裡的111表示的是該資料型別指定的顯示寬度。顯示寬度和資料型別的取值範圍是無關的 。顯示寬度只是指明MySQL最大可能顯示的數字個數,數值的位數小於指定的寬度時會由空格填充;如果插入大於顯示寬度的值,只要該值不超過該型別整數的取值範圍,數值一樣可以插入並能夠顯示出來。

例:建立表rmp1,其中欄位x、y、z、m、n資料型別依次為TINYINT、SMALLINT、MEDIUMINT、INT、BIGINT,SQL語句如下:

mysql> CREATE TABLE rmp1(x TINYINT, y SMALLINT, z MEDIUMINT, m INT, n BIGINT);
Query OK, 0 rows affected (2.13 sec)

查看錶結構:

mysql> DESC rmp1;
+-------+--------------+------+-----+---------+-------+
| Field | Type         | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| x     | tinyint(4)   | YES  |     | NULL    |       |
| y     | smallint(6)  | YES  |     | NULL    |       |
| z     | mediumint(9) | YES  |     | NULL    |       |
| m     | int(11)      | YES  |     | NULL    |       |
| n     | bigint(20)   | YES  |     | NULL    |       |
+-------+--------------+------+-----+---------+-------+
5 rows in set (0.19 sec)

可以看到系統給每一個欄位新增不同的預設使用寬度。
注:顯示寬度只用於顯示,並不能限制取值範圍和佔用空間,如:INT(3)會佔用4個位元組的儲存空間,但是允許的最大值是INT允許的最大值。

1.2浮點數型別和定點數型別
浮點型別有兩種:單精度浮點數型別(FLOAT)和雙精度浮點型別(DOUBLE)。
定點型別:DECIMAL。
這兩種型別均可以使用(M,N)表示,M(精度)表示總共的位數;N(標度)表示小數的位數。
MySQL中的小數型別

型別名稱 說明 儲存需求
FLOAT 單精度浮點數 4個位元組
DOUBLE 雙精度浮點數 8個位元組
DECIMAL (M,D) DEC 壓縮的“嚴格”定點數 M+2個位元組
不同型別的取值範圍:
資料型別 有符號 無符號
FLOAT -3.402823466E+38~-1.175494351E-38 0和1.175494351E-38~3.402823466E+38
DOUBLE -1.7976931348623157E+308~-2.2250738585072014E-308 0和2.2250738585072014E-308~1.7976931348623157E+308

提示:如果使用者指定的精度超出精度範圍,則會四捨五入進行處理。

例:建立表tmp2,其中欄位x、y、z資料型別依次為FLOAT(5,1)、DOUBLE(5,1)和DECIMAL(5,1),向表中插入資料5.12,5.15和5.123,SQL語句如下:

mysql> CREATE TABLE tmp2(x FLOAT(5,1), y DOUBLE(5,1), z DECIMAL(5,1));
Query OK, 0 rows affected (0.62 sec)

mysql> INSERT INTO tmp2 VALUES(5.12,5.15,5.123);
Query OK, 1 row affected, 1 warning (0.22 sec)

mysql> SHOW WARNINGS;
+-------+------+----------------------------------------+
| Level | Code | Message                                |
+-------+------+----------------------------------------+
| Note  | 1265 | Data truncated for column 'z' at row 1 |
+-------+------+----------------------------------------+
1 row in set (0.14 sec)

可以看到FLOAT和DOUBLE在進行四捨五入時沒有給出警告,但給出了z欄位數值被截斷警告。
檢視結果:

mysql> SELECT * FROM tmp2;
+------+------+------+
| x    | y    | z    |
+------+------+------+
|  5.1 |  5.2 |  5.1 |
+------+------+------+
1 row in set (0.18 sec)

FLOAT和DOUBLE在不指定精度時,預設會按照實際的精度,而DECIMAL在不指定精度時會預設(10,0)。
注:浮點數能表示更大的資料範圍,但會引起精度問題。

1.3日期與時間型別
MySQL中表示日期的資料型別:DATETIME、DATETIME、STAMP、TIME和YEAR。

型別名稱 日期格式 日期範圍 儲存需求
YEAR YYYY 1901~2155 1位元組
TIME HH:MM:SS -838:59:59~838:59:59 3位元組
DATE YYYY-MM-DD 1000-01-01~9999-12-31 3位元組
DATETIME YYYY-MM-DD HH-MM-SS 1000-01-01 00:00:00~9999-12-31 23:59:59 8位元組
TIMESTAMP YYYY-MM-DD HH:MM:SS 1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC 4位元組

1.year
可以使用下列格式指定YEAR的值:

  • 以4位字串或數字表示,即’YYYY’或者YYYY,範圍:‘1901’~‘2155’.
  • 以2位字串格式表示, ‘00’ ~ ‘69’ 和 ‘70’ ~ '99’範圍的值分別被轉換為2000~ 2069和1970~ 1999範圍的YEAR值。'0’與’00’的作用相同,若插入超過取值範圍的值將被轉換為2000。
  • 以2位數字表示與以字串格式表示類似。注意:這裡0值會被轉換成0000.

例:建立表tmp3,定義資料型別為YEAR的欄位y,向表中插入值為2010,‘2010’,‘2166’,SQL語句如下:

mysql> CREATE TABLE tmp3(y YEAR);
Query OK, 0 rows affected (1.78 sec)

mysql> INSERT INTO tmp3 values(2010),('2010'),('2166');
ERROR 1264 (22003): Out of range value for column 'y' at row 3

出現錯誤,超出範圍。(這裡與上面筆記所說不相符,大概是MySQL版本的問題)

例:向tmp3表中y欄位插入2位字串表示的YEAR值,分別為‘0’、‘00’、‘77’和‘10’,語句如下:

首先刪除表中資料
mysql> DELETE FROM tmp3;
Query OK, 0 rows affected (0.14 sec)

向表中插入資料
mysql> INSERT INTO tmp3 values('0'),('00'),('77'),('10');
Query OK, 4 rows affected (0.10 sec)
Records: 4  Duplicates: 0  Warnings: 0

檢視結果
mysql> SELECT * FROM tmp3;
+------+
| y    |
+------+
| 2000 |
| 2000 |
| 1977 |
| 2010 |
+------+
4 rows in set (0.02 sec)

其他就不一 一展示。

2.TIME
格式:

  • ‘D HH:MM:SS’/‘HH:MM:SS’/‘D HH:MM’/‘D HH’/‘SS’。這裡D表示日(0~34),在插入資料庫時,D被轉換為小時儲存,格式為“D*24+HH”。
  • ‘HHMMSS’。

例:建立資料表tmp4,定義資料型別為TIME欄位t,向表中插入值’10:05:05’,‘23:23’,‘2 10:10’,‘3 02’,‘10’,SQL語句如下:

mysql> CREATE TABLE tmp4(t TIME);
Query OK, 0 rows affected (0.56 sec)

mysql> INSERT INTO tmp4 VALUES('10:05:05'),('23:23'),('2 10:10'),('3 02'),('10');
Query OK, 5 rows affected (0.14 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp4;
+----------+
| t        |
+----------+
| 10:05:05 |
| 23:23:00 |
| 58:10:00 |
| 74:00:00 |
| 00:00:10 |
+----------+
5 rows in set (0.12 sec)

注:在使用D HH格式時,小時一定要使用雙位數。

例:向表tmp4中插入值’101112’,111213,‘0’,107010,SQL語句如下:
首先刪除資料:

mysql> DELETE FROM tmp4;
Query OK, 5 rows affected (0.18 sec)

向表中插入資料:

mysql> INSERT INTO tmp4 VALUES('10112'),(111213),('0'),(107010);
ERROR 1292 (22007): Incorrect time value: '107010' for column 't' at row 4

可以看到有錯誤產生,即在插入第4條資料時,資料超出了範圍,原因是70超出了60分鐘。

下面使用系統日期函式向TIME欄位插入值。
例:向tmp4插入系統當前時間,SQL語句如下:

mysql> INSERT INTO tmp4 VALUES(CURRENT_TIME),(NOW());
Query OK, 2 rows affected (0.18 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp4;
+----------+
| t        |
+----------+
| 08:43:00 |
| 08:43:00 |
+----------+
2 rows in set (0.00 sec)

1.3DATE型別(3bytes)

  1. ‘YYYY-MM-DD’ or 'YYYYMMDD’字元格式表示日期,取值範圍:
    ‘1000-0101’~ ‘9999-12-3’ 。

  2. ‘YY-MM-DD’~ 'YYMMDD’字元格式表示日期
    '00~ 69’表示‘2000 ~ 2069’
    '70~99’表示‘1970 ~1999’。

  3. YY-MM-DD or YYMMDD數字格式表示日期,範圍與2相似,但是YY-MM-DD需要用雙引號引上。

例:建立資料表tmp5,定義資料型別為DATE的欄位d,向表中插入“YYYY-MM-DD”和“YYYYMMDD”字串格式日期,SQL語句如下:

mysql> CREATE TABLE tmp5(d DATE);
Query OK, 0 rows affected (0.53 sec)

mysql> INSERT INTO tmp5 VALUES('1998-08-08'),('19980808'),('20101010');
Query OK, 3 rows affected (0.06 sec)

檢視結果:

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 1998-08-08 |
| 1998-08-08 |
| 2010-10-10 |
+------------+
3 rows in set (0.00 sec)

例:向tmp5表中插入“YY-MM-DD”和“YYMMDD”字串格式日期,SQL 語句如下:

mysql> DELETE FROM tmp5;
Query OK, 3 rows affected (0.06 sec)

mysql> INSERT INTO tmp5 VALUES('99-09-09'),('990909'),('000101'),('111111');
Query OK, 4 rows affected (0.11 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 1999-09-09 |
| 1999-09-09 |
| 2000-01-01 |
| 2011-11-11 |
+------------+
4 rows in set (0.00 sec)

例:向tmp5表中插入YY-MM-DD和YYMMDD數字格式日期,SQL語句如下:

mysql> INSERT INTO tmp5 VALUES("990909"),(990909),(000101),(111111);
Query OK, 4 rows affected (0.11 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 1999-09-09 |
| 1999-09-09 |
| 2000-01-01 |
| 2011-11-11 |
+------------+
4 rows in set (0.00 sec)

例:向tmp5插入系統當前日期:

mysql> DELETE FROM tmp5;
Query OK, 4 rows affected (0.08 sec)

mysql> INSERT INTO tmp5 VALUES(CURRENT_DATE()),(NOW());
Query OK, 2 rows affected, 1 warning (0.06 sec)
Records: 2  Duplicates: 0  Warnings: 1

mysql> SELECT * FROM tmp5;
+------------+
| d          |
+------------+
| 2018-11-30 |
| 2018-11-30 |
+------------+
2 rows in set (0.00 sec)

      CURRENT_DATE()只返回當前日期值
      NOW()返回日期和時間值,這裡d為DATE型別,故只儲存了DATE部分               

提示:MySQL允許不嚴格的語法:任何標點符號都可以用作日期部分之間的間隔符。

1.4DATETIME
格式:

  1. ‘YYYY-MM-DD HH:MM:SS’、‘YYYYMMDDHHMMSS’字串格式表示,取值範圍‘1000-01-01 00:00:00’~‘9999-12-3 23:59:59’。
  2. ‘YY-MM-DD HH:MM:SS’、‘YYMMDDHHMMSS’字串格式表示,取值範圍YY表示年值,其取值範圍與前面日期的相同。
  3. YYYYMMDDHHMMSS、YYMMDDHHMMSS數字格式表示。

例:建立資料表tmp6,定義資料型別為DATETIME的欄位dt,向表中插入日期和時間值(這裡只演示數字格式和插入系統當前日期和時間值)
建立資料表:

mysql> CREATE TABLE tmp6(dt DATETIME);
Query OK, 0 rows affected (0.46 sec)

插入值:

mysql> INSERT INTO tmp6 VALUES(19970823121314),(NOW());
Query OK, 2 rows affected (0.13 sec)
Records: 2  Duplicates: 0  Warnings: 0

檢視值:

mysql> SELECT * FROM tmp6;
+---------------------+
| dt                  |
+---------------------+
| 1997-08-23 12:13:14 |
| 2018-11-30 14:36:34 |
+---------------------+
2 rows in set (0.07 sec)

MySQL允許不嚴格的語法,實驗:
1

mysql> INSERT INTO tmp6 VALUES('2018$06&18 08\18+50');
ERROR 1292 (22007): Incorrect datetime value: '2018$06&18 0818+50' for column 'dt' at row 1

2

mysql> INSERT INTO tmp6 VALUES('2018$06&18 08/18?50');
Query OK, 1 row affected (0.14 sec)

3

mysql> INSERT INTO tmp6 VALUES('2018$06&18 08\18\15');
ERROR 1292 (22007): Incorrect datetime value: '2018$06&18 081815' for column 'dt' at row 

只有第2個可以插入。

5.TIMESTAMP
TIMESTAMP顯示格式與DATETIME相同,日期格式為:YYYY-MM-DD HH:MM:SS。但取值範圍比DATETIME小,其取值範圍為:‘1970-01-01 00:00:01’ UTC ~ ‘2038-01-19 03:14:07’ UTC,UTC:世界標準時間。

例:建立資料表tmp7,向表中插入值:

mysql> CREATE TABLE tmp7(ts TIMESTAMP);
Query OK, 0 rows affected (0.38 sec)
mysql> INSERT INTO tmp7 VALUES('[email protected]@12 [email protected]@12'),(NOW());
Query OK, 2 rows affected (0.15 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp7;
+---------------------+
| ts                  |
+---------------------+
| 1997-12-12 12:12:12 |
| 2018-11-30 14:52:11 |
+---------------------+
2 rows in set (0.00 sec)

TIMESTAMP儲存的時間與當前所處的時區有關。

例:向tmp7表中插入當前日期,檢視插入值,將時區改為東10區,再次檢視插入值:

mysql> DELETE FROM tmp7;
Query OK, 2 rows affected (0.13 sec)

mysql> INSERT INTO tmp7 VALUES(NOW());
Query OK, 1 row affected (0.06 sec)

mysql> SELECT * FROM tmp7;
+---------------------+
| ts                  |
+---------------------+
| 2018-11-30 14:55:07 |
+---------------------+
1 row in set (0.00 sec)

mysql> set time_zone='+10:00';
Query OK, 0 rows affected (0.06 sec)

mysql> SELECT * FROM tmp7;
+---------------------+
| ts                  |
+---------------------+
| 2018-11-30 16:55:07 |
+---------------------+
1 row in set (0.00 sec)

1.5字串型別
MySQL中的字串型別:

型別名稱 說明 儲存需求
CHAR(M) 固定長度非二進位制字串 M位元組,1<=M<=255
VARCHAR(M) 變長非二進位制字串 L+1位元組,L<=M,1<=M<=255
TINYTEXT 非常小的非二進位制字串 L+1位元組,L<2^8
TEXT 小的非二進位制字串 L+2位元組,L<2^16
MEDIUMTEXT 中等大小的非二進位制字串 L+3位元組,L<2^24
LONGTEXT 大的非二進位制字串 L+4位元組,L<2^32
ENUM 列舉型別,只能有一個列舉字串值 1或2個位元組,取決於列舉值的數目(最大值65535)
SET 一個設定,字串物件可以有0個或多個SET成員 1,2,3,4或8個位元組,取決於集合成員的數量(最多64個成員)

1.CHAR與VARCHAR
CHAR固定長度,當檢索到CHAR值時,尾部的空格將被刪除掉,且無論存入的長度為多少,所佔的空間均為定義時指定的字串列長。

VARCHAR在值儲存和檢索時尾部的空格仍保留,且其定義的列所佔的位元組數為實際長度加1。

例:建立tmp8表,定義欄位ch(CHAR(4)),vch(VARCHAR(4))向表中插入資料“ab ”,SQL語句如下:

mysql> CREATE TABLE tmp8(
    -> ch CHAR(4),
    -> vch VARCHAR(4)
    -> );
Query OK, 0 rows affected (1.51 sec)

mysql> INSERT INTO tmp8 VALUES('ab  ','ab  ')
    -> ;
Query OK, 1 row affected (0.16 sec)

查詢結果:

mysql> SELECT concat('(',ch,')'),concat('(',vch,')') FROM tmp8;
+--------------------+---------------------+
| concat('(',ch,')') | concat('(',vch,')') |
+--------------------+---------------------+
| (ab)               | (ab  )              |
+--------------------+---------------------+
1 row in set (0.21 sec)

可以看到,ch在儲存值時把尾部空格刪去,而vch仍保留尾部空格。

2.TEXT型別
TEXT列儲存非二進位制字串,如文章內容、評論等。
Text型別有四種:TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT。

3.ENUM型別
ENUM是一個字串物件,其值為表建立時在列規定中列舉的一列值。
語法格式:欄位名 ENUM('值 1' , '值 2' , ... , '值 n')
每個列舉值均有一個索引值,但是請注意儲存值不是一個十分明智的選擇,故一般儲存索引。
ENUM型別的取值範圍:

索引
NULL NULL
‘’ 0
first 1
second 2
third 3

例:建立表tmp9,定義ENUM型別的列enm(‘first’ , ‘second’ , ‘third’),檢視列成員的索引值:

mysql> CREATE TABLE tmp9(enm ENUM('first','second','third'));
Query OK, 0 rows affected (0.54 sec)

mysql> INSERT INTO tmp9 values('first'),('second'),('third'),(NULL);
Query OK, 4 rows affected (0.15 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> SELECT enm ,enm+0 FROM tmp9;
+--------+-------+
| enm    | enm+0 |
+--------+-------+
| first  |     1 |
| second |     2 |
| third  |     3 |
| NULL   |  NULL |
+--------+-------+
4 rows in set (0.54 sec)

我試了一下,發現我mysql版本無法輸入‘’,我想應該是需要更高的版本吧!

4.set型別
例:建立表tmp11,定義set型別欄位,取值列表為(‘a’,‘b’,‘c’,‘d’),插入資料(‘a’),(‘a,b,a’),(‘c,a,d’),(‘a,x,b,y’),SQL語句如下:

mysql> CREATE TABLE tmp11(s SET('a','b','c','d'));
Query OK, 0 rows affected (0.37 sec)

mysql> INSERT INTO tmp11 VALUES('a'),('a,b,a'),('c,a,b'),('a,x,b,y');
ERROR 1265 (01000): Data truncated for column 's' at row 4

可以看到由於插入了SET列不支援的型別,出現錯誤。
重新插入

mysql> INSERT INTO tmp11 VALUES('a'),('a,b,a'),('c,a,b');
Query OK, 3 rows affected (0.04 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM tmp11;
+-------+
| s     |
+-------+
| a     |
| a,b   |
| a,b,c |
+-------+
3 rows in set (0.00 sec)

從結果可以看出,set不允許重複,且有先後順序明確。

1.5 二進位制型別
MySQL支援兩類字元型資料:文字字串、二進位制字串。
二進位制資料型別有:BIT、BINARY、VARBINARY、TINYBLOB、BLOB、MEDIUMBOLB、LONGBLOB。

1.BIT型別
BIT資料型別用來儲存位欄位值,BIT(M),M表示每個值的位數,範圍1~64。若M被忽略,預設1。
例:建立表tmp12,定義BIT(4)型別的欄位b,向表中插入資料2、9、15、16。

mysql> INSERT INTO tmp12 VALUES(2),(9),(15),(16);
ERROR 1406 (22001): Data too long for column 'b' at row 4

出現錯誤,16超出了4位二進位制數的範圍。

mysql> SELECT BIN(b+0) FROM tmp12;
+----------+
| BIN(b+0) |
+----------+
| 10       |
| 1001     |
| 1111     |
+----------+
3 rows in set (0.09 sec)

mysql> SELECT b+0 FROM tmp12;
+------+
| b+0  |
+------+
|    2 |
|    9 |
|   15 |
+------+
3 rows in set (0.00 sec)

其中: b+0表示將二進位制的結果轉換為對應的數字值,BIN()函式將數字轉化為二進位制。

2.BINARY和VARBINARY
BINARY和VARBINARY類似於CHAER和VARCHAR,BINARY型別的長度是固定的,VARBINARY型別的長度是可變的且實際佔用空間為字串實際長度加一。
例:建立表tmp13,定義BINARY(3)型別欄位b和VARBINARY(3)型別的欄位vb,並向表中插入資料‘5’,比較兩個欄位的儲存空間:

mysql> CREATE TABLE tmp13(b BINARY(3),vb VARBINARY(3));
Query OK, 0 rows affected (0.34 sec)

mysql> INSERT INTO tmp13 VALUES(5,5);
Query OK, 1 row affected (0.02 sec)

mysql> SELECT length(b),length(vb) FROM tmp13;
+-----------+------------+
| length(b) | length(vb) |
+-----------+------------+
|         3 |          1 |
+-----------+------------+
1 row in set (0.00 sec)

進一步確認5在兩個欄位中不同的儲存方式:

mysql> SELECT b,vb,b='5',b='5\0\0',vb='5',vb='5\0\0' FROM tmp13;
+------+------+-------+-----------+--------+------------+
| b    | vb   | b='5' | b='5\0\0' | vb='5' | vb='5\0\0' |
+------+------+-------+-----------+--------+------------+
| 5    | 5     |       0 |            1 |         1 |               0 |
+------+------+-------+-----------+--------+------------+
1 row in set (0.00 sec)

b欄位不足的空間填充了‘\0’。

3.BOLB型別
BLOB型別的儲存範圍:

資料型別 儲存範圍
TINYBLOB 最大長度為255(28-1)位元組
BLOB 最大長度為65535(216-1)位元組
MEDIUMBLOB 最大長度為16777215(224-1)位元組
LONGBLOB 最大長度為4294967295或4GB(232-1)位元組

BLOB列儲存的是二進位制字串(位元組字串);TEXT列儲存的是字元字串。BLOB列沒有字符集,並且排序和比較基於列位元組的數值;TEXT列有一個字符集,並且根據字符集對值進行排序和比較。