表完整性約束
-
創建表的完整語法
create table 表名( 字段名1 類型[(寬度) 約束條件], 字段名2 類型[(寬度) 約束條件], 字段名3 類型[(寬度) 約束條件] );
注意事項:
- 在同一表中,字段名不能相同。
- 字段名和類型必須,寬度約束條件可選。
- 最后一個字段不能加逗號。
表中的數據類型
介紹
存儲引擎決定了表的類型,表里面的數據也得有類型,數據還得有寬度,寬度是可選的。別問,問就是記。
建表的時候,字段都有對應的數據類型:
整型、浮點型、字符類型(char 與 varchar)、日期類型、枚舉與集合
數值類型
強調:對於整型來說,數據類型后的寬度並不是存儲限制。
-
整型
-
TINYINT:小整數(默認有符號)
-
有符號:-128 ~ 127
-
無符號:0 ~ 255
-
有符號和無符號TINYINT
=================有符號:默認有符號,即數字前有正負號=========== create table t1(id tinyint); insert into t1 values(-128); #插入成功 insert into t1 values(-129); #插入失敗,5.7版本報錯:ERROR 1264 (22003): Out of range value for column 'id' at row 1。之前版本不會報錯,會將 -129 存成 -128 insert into t1 values(127); #插入成功 insert into t1 values(128); #插入失敗,5.7版本報錯。之前版本不會報錯,會將128存成127 ===================無符號:范圍在 0~255====================== create table t2(id tinyint unsigned); insert into t2 values(-1); 插入失敗,5.7之前版本會將 -1 存成 0。 其余結果就不一一演示了。 ===================zerofill測試整數類型的顯示寬度=============================== mysql> insert into zerofilltable values(1),(11),(111),(1111) mysql> select * from zerofilltable; +------+ | id | +------+ | 001 | | 011 | | 111 | | 1111 | +------+ 4 rows in set (0.00 sec)
注意:MySQL中沒有布爾值,用 tinyint(1) 構造。
-
-
SMALLINT
-
MEDIUMINT
-
INT:整數
- 有符號:-2147483648 ~ 2147483647
- 無符號:0 ~ 4294967295
-
BIGINT:大整數
- 有符號:-9223372036854775808 ~ 9223372036854775807
- 無符號: 0 ~ 18446744073709551615
-
-
浮點型
- float
- 有符號:-3.402823466E+38 to -1.175494351E-38; 1.175494351E-38 to 3.402823466E+38
- 無符號:1.175494351E-38 to 3.402823466E+38
- double
- 有符號: -1.7976931348623157E+308 to -2.2250738585072014E-308;2.2250738585072014E-308 to 1.7976931348623157E+308
- 無符號:2.2250738585072014E-308 to 1.7976931348623157E+308
======================float [(M,D)] [UNSIGNED] [ZEROFILL]====================== 定義:單精度浮點數(非准確小數值),m是數字總個數,d是小數點后個數。m最大值為255,d最大值為30 精確度:隨着小數的增多,精度變得不准確。 ======================double [(M,D)] [UNSIGNED] [ZEROFILL]====================== 定義:雙精度浮點數(非准確小數值),m是數字總個數,d是小數點后個數。m最大值為255,d最大值為30 精確度:隨着小數的增多,精度比float要高,但也會變得不准確 ======================decimal [(M,D)] [UNSIGNED] [ZEROFILL]====================== 定義:准確的小數值,m是數字總個數(負號不算),d是小數點后個數。 m最大值為65,d最大值為30。 精確度:隨着小數的增多,精度始終准確。 對於精確數值計算時需要用此類型,decaimal能夠存儲精確值的原因在於其內部按照字符串存儲。 create table t12(id FLOAT(255,30)); create table t13(id DOUBLE(255,30)); create table t14(id DECIMAL(65,30)); insert into t12 values(1.111111111111111111111111111111); insert into t13 values(1.111111111111111111111111111111); insert into t14 values(1.111111111111111111111111111111); mysql> select * from t1; +----------------------------------+ | id | +----------------------------------+ | 1.111111164093017600000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t2; +----------------------------------+ | id | +----------------------------------+ | 1.111111111111111200000000000000 | +----------------------------------+ 1 row in set (0.00 sec) mysql> select * from t3; +----------------------------------+ | id | +----------------------------------+ | 1.111111111111111111111111111111 | +----------------------------------+ 1 row in set (0.00 sec) 精確度: float < double < decimal
- float
時間類型
YEAR
YYYY(1901/2155)
DATE
YYYY-MM-DD(1000-01-01/9999-12-31)
TIME
HH:MM:SS('-838:59:59'/'838:59:59')
DATETIME
YYYY-MM-DD HH:MM:SS(1000-01-01 00:00:00/9999-12-31 23:59:59 Y)
TIMESTAMP
YYYYMMDD HHMMSS(1970-01-01 00:00:00/2037 年某時)
===================================date,time,datetime===================================
mysql> create table t2(d date, t time, dt datetime);
Query OK, 0 rows affected (0.03 sec)
mysql> insert into t2 values(now(), now(), now());
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> select * from t2;
+------------+----------+---------------------+
| d | t | dt |
+------------+----------+---------------------+
| 2019-08-19 | 23:32:13 | 2019-08-19 23:32:13 |
+------------+----------+---------------------+
1 row in set (0.00 sec)
==============================================timestamp==================================
mysql> create table t3(timestamp_ timestamp);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t3 values(now());
Query OK, 1 row affected (0.01 sec)
mysql> select * from t3;
+---------------------+
| timestamp_ |
+---------------------+
| 2019-08-19 23:35:12 |
+---------------------+
1 row in set (0.00 sec)
==============================================year=======================================
mysql> insert into t1 values(now());
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+-----------+
| born_year |
+-----------+
| 2001 |
| 1990 |
| 2017 |
| 2019 |
+-----------+
4 rows in set (0.00 sec)
1. 單獨插入時間時,需要以字符串的形式,按照對應的格式插入
2. 插入年份時,盡量使用4位值
3. 插入兩位年份時,<=69,以20開頭,比如50, 結果2050
>=70,以19開頭,比如71,結果1971
MariaDB [db1]> create table t12(y year);
MariaDB [db1]> insert into t12 values
-> (50),
-> (71);
MariaDB [db1]> select * from t12;
+------+
| y |
+------+
| 2050 |
| 1971 |
+------+
datetime 與 timestamp 的區別:
datetime沒有默認值時,插入空值會是個null。必須指定默認值:not null default now() 才會自動填入當前時間。
timestamp,不需要任何設置,在傳空值的情況下自動傳入當前時間。
mysql> create table t1(t datetime);
Query OK, 0 rows affected (0.02 sec)
mysql> create table t2(t timestamp);
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t1 values();
Query OK, 1 row affected (0.00 sec)
mysql> select * from t1;
+------+
| t |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
mysql> insert into t2 values();
Query OK, 1 row affected (0.01 sec)
mysql> select * from t2;
+---------------------+
| t |
+---------------------+
| 2019-08-19 23:49:16 |
+---------------------+
1 row in set (0.00 sec)
mysql> create table t3(t datetime not null default now());
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t3 values();
Query OK, 1 row affected (0.00 sec)
mysql> select * from t3;
+---------------------+
| t |
+---------------------+
| 2019-08-19 23:50:00 |
+---------------------+
1 row in set (0.00 sec)
例題
創建一個學生表,這個學生表字段為:id, 姓名,出生日期,出生年份,注冊時間。
create table student(
id int,
name varchar(100),
born_year year,
born_time datetime,
register_time timestamp
);
mysql> desc student;
+---------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+-------------------+-----------------------------+
| id | int(11) | YES | | NULL | |
| name | varchar(100) | YES | | NULL | |
| born_year | year(4) | YES | | NULL | |
| born_time | datetime | YES | | NULL | |
| register_time | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+---------------+--------------+------+-----+-------------------+-----------------------------+
5 rows in set (0.00 sec)
mysql> insert into student values(1, '游哥', 2001, '2001-9-10');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> insert into student values(1, '游哥', 2001, '2001-9-10', null);
Query OK, 1 row affected (0.00 sec)
mysql> select * from student;
+------+--------+-----------+---------------------+---------------------+
| id | name | born_year | born_time | register_time |
+------+--------+-----------+---------------------+---------------------+
| 1 | 游哥 | 2001 | 2001-09-10 00:00:00 | 2019-08-19 23:58:51 |
+------+--------+-----------+---------------------+---------------------+
1 row in set (0.00 sec)
字符串類型( var 和 varchar )
create table t15(name char(4));
create table t16(name varchar(4));
-
char:定長,簡單粗暴,浪費空間,存取速度快
字符長度范圍:0-255(一個中文是一個字符,是utf8編碼的3個字節) 存儲: 存儲char類型的值時,會往右填充空格來滿足長度 例如:指定長度為10,存>10個字符則報錯,存<10個字符則用空格填充直到湊夠10個字符存儲 檢索: 在檢索或者說查詢時,查出的結果會自動刪除尾部的空格,除非我們打開pad_char_to_full_length SQL模式(SET sql_mode = 'PAD_CHAR_TO_FULL_LENGTH';)
-
varchar:變長,精准,節省空間,存取速度慢(較於char比較慢)
字符長度范圍:0-65535(如果大於21845會提示用其他類型 。mysql行最大限制為65535字節 存儲: 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) 檢索: 尾部有空格會保存下來,在檢索或者說查詢時,也會正常顯示包含空格在內的內容
存的時候 需要給數據一個記錄長度的報頭
取的時候 需要先讀取報頭才能讀取真實數據
-
char 與 varchar :
char 取的時候方便,直接按固定長度取即可。
varchar 取的時候繁瑣,無法知道數據多長。
mysql> create table t1(name char(4)); Query OK, 0 rows affected (0.02 sec) mysql> create table t2(name varchar(4)); Query OK, 0 rows affected (0.02 sec) mysql> insert into t1 values('hello'); #超出四個字符報錯,不夠四個字符空格補全 ERROR 1406 (22001): Data too long for column 'name' at row 1 mysql> insert into t1 values('hell'); Query OK, 1 row affected (0.00 sec) mysql> insert into t2 values('11111111'); #超出四個字符報錯,不夠四個有幾個就存幾個 ERROR 1406 (22001): Data too long for column 'name' at row 1 mysql> insert into t2 values('hell'); Query OK, 1 row affected (0.00 sec) mysql> select * from t1; +------+ | name | +------+ | hell | +------+ 1 row in set (0.00 sec) mysql> select * from t2; +------+ | name | +------+ | hell | +------+ 1 row in set (0.00 sec) 了解兩個函數 length:查看字節數 char_length:查看字符數 mysql> select char_length(name) from t1; +-------------------+ | char_length(name) | +-------------------+ | 4 | +-------------------+ 1 row in set (0.00 sec) mysql> select char_length(name) from t2; +-------------------+ | char_length(name) | +-------------------+ | 4 | +-------------------+ 1 row in set (0.00 sec) """ 首先應該肯定的是在硬盤上存的絕對是真正的數據,但顯示的時候mysql會自動將末尾的空格取掉,如果不想讓mysql幫你做自動去除末尾空格的操作,需要再添加一個模式 """ set global sql_mode="strict_trans_tables,PAD_CHAR_TO_FULL_LENGTH"; ''' 針對char類型,mysql在存儲時會將數據用空格補全存放到硬盤中。但是會在讀出結果的時候自動取掉末尾的空格 ''' name char(5) # 缺點:浪費空間 # 優點:存取速度都快 egon alex lxx jxx txx name varchar(5) # 缺點:存取速度慢 # 優點:節省空間 1bytes+egon 1bytes+alex 1bytes+lxx 1bytes+jxx 1bytes+txx
-
concat
-
mysql> select concat('數據: ',x,'長度: ',char_length(x)),concat(y,char_length(y) ) from t1; +------------------------------------------------+--------------------------+ | concat('數據: ',x,'長度: ',char_length(x)) | concat(y,char_length(y)) | +------------------------------------------------+--------------------------+ | 數據: 你瞅啥 長度: 5 | 你瞅啥 4 | +------------------------------------------------+--------------------------+ 1 row in set (0.00 sec)
-
總結
#InnoDB存儲引擎:建議使用VARCHAR類型 單從數據類型的實現機制去考慮,char數據類型的處理速度更快,有時甚至可以超出varchar處理速度的50%。 但對於InnoDB數據表,內部的行存儲格式沒有區分固定長度和可變長度列(所有數據行都使用指向數據列值的頭指針),因此在本質上,使用固定長度的CHAR列不一定比使用可變長度VARCHAR列性能要好。因而,主要的性能因素是數據行使用的存儲總量。由於CHAR平均占用的空間多於VARCHAR,因此使用VARCHAR來最小化需要處理的數據行的存儲總量和磁盤I/O是比較好的。 #其他字符串系列(效率:char>varchar>text) TEXT系列 TINYTEXT TEXT MEDIUMTEXT LONGTEXT BLOB 系列 TINYBLOB BLOB MEDIUMBLOB LONGBLOB BINARY系列 BINARY VARBINARY text:text數據類型用於保存變長的大字符串,可以組多到65535 (2**16 − 1)個字符。 mediumtext:A TEXT column with a maximum length of 16,777,215 (2**24 − 1) characters. longtext:A TEXT column with a maximum length of 4,294,967,295 or 4GB (2**32 − 1) characters.
-
枚舉類型和集合類型
字段的值只能在給定范圍內選擇,如單選框,多選框。
枚舉: enum 多選一
mysql> create table shirts(
-> name varchar(40),
-> size enum('s', 'l', 'x', 'xxl'));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into shirts values('dress', 's'), ('youyiku', 'x');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from shirts;
+---------+------+
| name | size |
+---------+------+
| dress | s |
| youyiku | x |
+---------+------+
2 rows in set (0.00 sec)
=====================================只插入一個值====================================
mysql> insert into shirts(name) values('haha');
Query OK, 1 row affected (0.00 sec)
mysql> select * from shirts;
+---------+------+
| name | size |
+---------+------+
| dress | s |
| youyiku | x |
| haha | NULL |
+---------+------+
3 rows in set (0.00 sec)
===========================枚舉類型不一致會報錯=========================================
mysql> insert into shirts values('der', 'asd');
ERROR 1265 (01000): Data truncated for column 'size' at row 1
集合:set 多選多
==========================建表==========================
mysql> create table teacher(
-> id int,
-> name char(16),
-> gender enum('male', 'female', 'others'),
-> hobby set('pingpang', 'basketball', 'soccer'));
Query OK, 0 rows affected (0.02 sec)
=========================插入=========================
mysql> insert into teacher values(1, 'egon', 'male', 'soccer,pingpang');
Query OK, 1 row affected (0.00 sec)
注意:插入的時候,set多選的值之間不能有其他的東西,如多了個空格之類的神奇玩意;
========================查詢====================
mysql> select * from teacher;
+------+------+--------+-----------------+
| id | name | gender | hobby |
+------+------+--------+-----------------+
| 1 | NULL | female | soccer |
| 1 | egon | male | soccer |
| 1 | egon | male | pingpang,soccer |
+------+------+--------+-----------------+
3 rows in set (0.00 sec)