1. 程式人生 > 其它 >MySQL表相關操作

MySQL表相關操作

目錄

MySQL表相關操作

一 表相關操作基礎

1 表介紹

	表相當於檔案,表中的一條記錄就相當於檔案的一行內容,不同的是,表中的一條記錄有對應的標題,稱為表的欄位。
id name age 欄位:一條記錄對應的標題稱為一個欄位,如id,name,age
1 kiessling 37 記錄:一行內容稱為一條記錄
2 lars 30
3 leno 28

2 建立表

2.1 語法及注意事項

create table 表名(
欄位名1 型別[(寬度) 約束條件],
欄位名2 型別[(寬度) 約束條件],
欄位名3 型別[(寬度) 約束條件]
);
## 注意:
    1).在同一張表中,欄位名是不能相同的;

    2).寬度和約束條件可選;

    3).欄位名和型別是必須的;

    4).表中的最後一個欄位不要加逗號!!"

2.2 程式碼示例:

mysql> create database db1 charset utf8;  # 建立庫並指定字元編碼(資料夾) 
mysql> use db1;  # 切換資料夾
mysql> create table t1(    # 建立表,並指定欄位,資料型別
    -> id int,             # 一般建立表必指定的欄位
    -> name varchar(50),
    -> sex enum('male','female'),
    -> age int(3)    # 整型欄位後面指定的是顯示長度,不是資料實際的儲存長度
    -> );
mysql> show tables; #檢視db1庫下所有表名
mysql> desc t1;  # 查看錶的結構
mysql> select id,name,sex,age from t1;  # 檢視指定欄位的內容
mysql> select * from t1;  # 查看錶的所有內容
mysql> insert into t1 values  # into可省略
    -> (1,'egon',18,'male'),
    -> (2,'alex',81,'female')
    -> ;
mysql> insert into t1(id) values  # 插入值全為NULL
    -> (3),
    -> (4);

3 查看錶結構

MariaDB[db1]> describe t1;  # 查看錶結構,可簡寫為desc 表名
+-------+-----------------------+------+-----+---------+-------+
| Field | Type                  | Null | Key | Default | Extra |
+-------+-----------------------+------+-----+---------+-------+
| id    | int(11)               | YES  |     | NULL    |       |
| name  | varchar(50)           | YES  |     | NULL    |       |
| sex   | enum('male','female') | YES  |     | NULL    |       |
| age   | int(3)                | YES  |     | NULL    |       |
+-------+-----------------------+------+-----+---------+-------+

MariaDB [db1]> show create table t1\G; # 查看錶詳細結構,可加\G

4 修改表

4.1 修改表名

alter table 表名 rename 新表名;

4.2 修改欄位

alter table 表名 modify 欄位名 資料型別 [完整性約束條件];
alter table 表名 change 舊欄位名 新欄位名 舊資料型別 [完整性約束條件];
alter table 表名 change 舊欄位名 新欄位名 新資料型別 [完整性約束條件];

4.3 增加欄位

alter table 表名 add 欄位名 資料型別 [完整性約束條件],
				add 欄位名 資料型別 [完整性約束條件];
alter table 表名 add 欄位名 資料型別 [完整性約束條件] first;
alter table 表名 add 欄位名 資料型別 [完整性約束條件] after 欄位名;

4.4 刪除欄位

alter table 表名 drop 欄位名;

4.5 程式碼示例

1) 先建立庫,在新建表mysql> create database db1;mysql> user db1mysql> create table t1(id int,name char(4));# mysql> alter table t1 rename tt1;  # 表名的修改2) 修改儲存引擎mysql> alter table t1 engine=innodb;3) 修改欄位mysql> alter table t1 modify id tinyint;  # 修改欄位的資料型別mysql> alter table t1 change id ID tinyint;  # 修改欄位名及資料型別mysql> alter table t1 change ID id tinyint,change name NAME char(4);  # 修改多個欄位名及資料型別4) 增加欄位mysql> alter table t1 add gender char(4);mysql> desc t1;+--------+------------+------+-----+---------+-------+| Field  | Type       | Null | Key | Default | Extra |+--------+------------+------+-----+---------+-------+| id     | tinyint(4) | YES  |     | NULL    |       || NAME   | char(4)    | YES  |     | NULL    |       || gender | char(4)    | YES  |     | NULL    |       |+--------+------------+------+-----+---------+-------+mysql> alter table t1 add gender char(4) first;mysql> alter table t1 add level int after ID;5) 刪除欄位alter table t1 drop gender;mysql> desc t1;+-------+------------+------+-----+---------+-------+| Field | Type       | Null | Key | Default | Extra |+-------+------------+------+-----+---------+-------+| id    | tinyint(4) | YES  |     | NULL    |       || NAME  | char(4)    | YES  |     | NULL    |       |+-------+------------+------+-----+---------+-------+

5 表字段的資料型別

5.1 介紹

	儲存引擎決定了表的型別,而表記憶體放的資料也要有不同的型別,每種資料型別都有自己的寬度,但是寬度是可選的。# 1.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. 列舉型別與集合型別

5.2 數值型別

5.2.1 整數型別
	整數型別: TINYINT SMALLINT MEDIUMINT INT BIGINT	作用:儲存年齡,等級,id,各種號碼等。	# 強調:"整型的寬度是顯示寬度(如tinyint(4) ) ",無需設定,儲存寬度是固定死的。預設的顯示寬度,都是在最大值的基礎上加1。	
# 常用型別詳解========================================        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
#	程式碼驗證:# 1、=====================表字段型別之整型=======================# =========有符號和無符號tinyint==========# tinyint預設為有符號mysql> insert t4 values(128);  ERROR 1264 (22003): Out of range value for column 'id' at row 1  # 嚴格模式,超出範圍會報錯,若不是嚴格模式,則會把數字存成最近的極值。mysql> insert t4 values(127);Query OK, 1 row affected (0.01 sec)mysql> select * from t4;+------+| id   |+------+|  127 |+------+1 row in set (0.00 sec)
"型別" "大小" "範圍(有符號) " "範圍(無符號) " "用途"
TINYINT 1 位元組 (-128,127) (0,255) 小整數值
SMALLINT 2 位元組 (-32 768,32 767) (0,65 535) 大整數值
MEDIUMINT 3 位元組 (-8 388 608,8 388 607) (0,16 777 215) 大整數值
INT或INTEGER 4 位元組 (-2 147 483 648,2 147 483 647) (0,4 294 967 295) 大整數值
BIGINT 8 位元組 (-9 233 372 036 854 775 808,9 223 372 036 854 775 807) (0,18 446 744 073 709 551 615) 極大整數值
FLOAT 4 位元組 (-3.402 823 466 E+38,1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) 0,(1.175 494 351 E-38,3.402 823 466 E+38) 單精度,浮點數值
DOUBLE 8 位元組 (1.797 693 134 862 315 7 E+308,2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) 雙精度,浮點數值
DECIMAL 對DECIMAL(M,D) ,如果M>D,為M+2否則為D+2 依賴於M和D的值 依賴於M和D的值 小數值
1)  int的儲存寬度是4Bytes,即32個bit,即2"32;2)  無符號最大值:4294967296-1;3)  有符號最大值:2147483648-1;4)  有符號和無符號的最大數字需要的顯示寬度均為10,而針對有符號的最小值則需要11位才能完全顯示,所以int型別預設的顯示寬度為11是非常合理的。5)  最後,整型型別,其實沒有必要指定顯示寬度,使用預設的就OK。
5.2.2 浮點型
定點數型別 DEC等同於DECIMAL浮點型別:float double作用:儲存薪資、身高、體重、體質引數等
# 常用型別詳解======================================float[(M,D) [unsigned] [zerofill]]定義:	單精度浮點數(非準確小數) ,m是數字總個數,d是小數點後個數。m最大值為255,d最大值為30。有符號:		-3.402823466E+38 to -1.175494351E-38,					1.175494351E-38 to 3.402823466E+38無符號:		1.175494351E-38 to 3.402823466E+38精確度:		"" 隨著小數的增多,精度變得不準確 ""======================================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要高,但也會變得不準確 ""======================================decimal[(M,D) [unsigned] [zerofill]]定義:		準確的小數值,m是數字總個數(符號不算) ,d是小數點後個數。m最大值為65,d最大值為30。精確度:		"" 隨著小數的增多,精度始終準確 ""        對於精確數值計算時需要用此型別        decaimal能夠儲存精確值的原因在於其內部按照字串儲存。
# 2、=====================表字段型別之浮點型別=======================mysql> create table t7(x float(255,30),y double(255,30),z decimal(65,30));mysql> insert t7 values(1.11111111111111111111,1.11111111111111111111,1.11111111111111111111);mysql> select * from t7;  # 顯示的精度問題,decimal精度最高+----------------------------------+----------------------------------+----------------------------------+| x                                | y                                | z                                |+----------------------------------+----------------------------------+----------------------------------+| 1.111111164093017600000000000000 | 1.111111111111111200000000000000 | 1.111111111111111111110000000000 |+----------------------------------+----------------------------------+----------------------------------+1 row in set (0.00 sec)

5.3 日期型別

	date time datetime timestamp year	作用:儲存使用者註冊時間,文章釋出時間,員工入職時間,出生時間,過期時間等等。
year(1901/2155) time 時:分:秒 ('-838:59:59'/'838:59:59') date 年:月:日 (1000-01-01/9999-12-31) datetime 年:月:日 時:分:秒 1000-01-01 00:00:00/9999-12-31 23:59:59timestamp 年:月:日 時:分:秒 1970-01-01 00:00:00/2037
# 3、=====================表字段型別之日期型別======================# 使用函式now()mysql> create table t8(y year,t time,d date,dt datetime,ts timestamp);Query OK, 0 rows affected (0.03 sec)mysql> insert t8 values(now(),now(),now(),now(),now());Query OK, 1 row affected, 1 warning (0.01 sec)mysql> select * from t8;+------+----------+------------+---------------------+---------------------+| y    | t        | d          | dt                  | ts                  |+------+----------+------------+---------------------+---------------------+| 2020 | 11:09:30 | 2020-09-02 | 2020-09-02 11:09:30 | 2020-09-02 11:09:30 |+------+----------+------------+---------------------+---------------------+# 手動傳時間引數mysql> create table student(id int,name char(10),born_year year,birth date,reg_time datetime);Query OK, 0 rows affected (0.03 sec)mysql> insert student values(1,"xxx","1911","1911-11-11","1911-11-11 11:11:11");Query OK, 1 row affected (0.01 sec)mysql> select * from student;+------+------+-----------+------------+---------------------+| id   | name | born_year | birth      | reg_time            |+------+------+-----------+------------+---------------------+|    1 | xxx  |      1911 | 1911-11-11 | 1911-11-11 11:11:11 |+------+------+-----------+------------+---------------------+1 row in set (0.00 sec)============!!!注意!!!!!!!===========1) 單獨插入時間是,需要以字串的顯露出,按照對應的格式插入2) 插入年份時,儘量使用4位值3) 插入兩位年份時,<=69,以20開頭,比如50,結果2050      				>=70,以19開頭,比如71,結果1971
5.3.1 datetime與timestamp的區別
# 在實際應用的很多場景中,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或者timestamp如果是用作註冊時間,那麼指定not null default now()自動填充時間即可,如果是用作更新時間那麼需要額外指定on update now(),該配置timestamp自帶。
# 測試1:基礎性質mysql> create table t9(reg_time datetime not null default now());mysql> create table t10(reg_time timestamp);mysql> insert t9 values();mysql> insert t10 values();mysql> select * from t9;+---------------------+| reg_time            |+---------------------+| 2020-09-02 11:28:40 |+---------------------+mysql> select * from t10;+---------------------+| reg_time            |+---------------------+| 2020-09-02 11:28:49 |+---------------------+mysql> desc t9;  # 用於記錄註冊時間,+----------+----------+------+-----+-------------------+-------+| Field    | Type     | Null | Key | Default           | Extra |+----------+----------+------+-----+-------------------+-------+| reg_time | datetime | NO   |     | CURRENT_TIMESTAMP |       |+----------+----------+------+-----+-------------------+-------+mysql> desc t10;  # 用於記錄更新時間+----------+-----------+------+-----+-------------------+-----------------------------+| Field    | Type      | Null | Key | Default           | Extra                       |+----------+-----------+------+-----+-------------------+-----------------------------+| reg_time | timestamp | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |+----------+-----------+------+-----+-------------------+-----------------------------+
# 測試2:mysql> create table t9(    ->     id int,    ->     name varchar(16),    ->     -- update_time datetime not null default now() on update now()  # --是註釋的意思,    ->     update_time timestamp,    ->     reg_time datetime not null default now()    -> );mysql> insert into t9(id,name) values(1,"xxx");# 測試效果mysql> select * from t9;+------+------+---------------------+---------------------+| id   | name | update_time         | reg_time            |+------+------+---------------------+---------------------+|    1 | xxx  | 2020-09-02 11:37:21 | 2020-09-02 11:37:21 |+------+------+---------------------+---------------------+mysql> update t9 set name="XXXX" where id=1;mysql> select * from t9;+------+------+---------------------+---------------------+| id   | name | update_time         | reg_time            |+------+------+---------------------+---------------------+|    1 | XXXX | 2020-09-02 11:39:13 | 2020-09-02 11:37:21 |+------+------+---------------------+---------------------+

5.4 字串型別

5.4.1 基本情況
# 注意:char和varchar括號內的引數指的都是字元的長度1) char型別:定長,簡單粗暴,浪費空間,存取速度快	字元長度範圍:0-255(一個波斯文是一個字元,是utf8編碼的3個位元組) 	儲存:		儲存char型別的值時,會往右填充空格來滿足長度(底層邏輯,查詢時查不到) 		例如:指定長度為10,存>10個字元則報錯,存<10個字元則用空格填充直到湊夠10個儲存字元。	檢索:		在檢索或者說查詢時,查處的結果會自動刪除尾部的空格,除非我們開啟pad_char_to_full_length SQL模式(SET sql_mode='PAD_CHAR_TO_FULL_LENGTH';)。		2) 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對roe的最大位元組限制數,即已足夠使用) ;		如果真實資料<255Bytes則需要1Bytes的字首(1Bytes=8bit 2"8最大表示的數字為255) ;		如果真實資料>255Bytes則需要2Bytes的字首(2Bytes=16bit 2"16最大表示的數字為65535) ;	檢索:尾部有空格會儲存下來,在檢索或者說查詢時,也會正常顯示包含空格在內的內容;
"示例:"以4位元組為例,"對比char與varchar儲存空間數量"。"特殊情況:"在接近資料儲存滿的時候,varchar反而更費空間。
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
5.4.2 基本使用驗證
# 函數了解length: 檢視位元組數char_length: 檢視字元數
# 驗證create table t11(x char(5));create table t12(x varchar(5));# 實際數字後面加一個空格insert t11 values("我擦嘞 ");  -- "我擦嘞  "insert t12 values("我擦嘞 ");  -- "我擦嘞 "t11=>字元個數 5  位元組個數 11  # 實際的字元、位元組數t11=>字元個數 3   # char顯示的字元t12=>字元個數 4  位元組個數 10  # varchar可以顯示實際的字元、位元組數(位元組數上添加了一個位數) varchar認為末尾的空格不是資料的一部分。# 查詢當前的模式show variables like "sql_mode"set sql_mode="pad_char_to_full_length";  # 嚴格模式下可以看見實際的字元和位元組個數,預設的模式下不是這樣顯示select char_length(x) from t11;select char_length(x) from t12;select length(x) from t11;select length(x) from t12;# 查詢時預設把末尾的空格都去掉 like模糊匹配,=匹配select * from 表名 where 欄位 like "r%"  # like模糊匹配,r開頭的資料,後面字元數不限select * from 表名 where 欄位 like "r_"  # r開頭的資料,後面只有一個字元。
5.4.3 總結
# InnoDB儲存引擎:建議使用VARCHAR資料型別	單從資料型別的實現機制去考慮,char資料型別的處理速度更快,有時甚至可以超出varchar處理速度的50%。但對於InnoDB資料表,內部的行儲存格式沒有區分固定長度和可變長度列(所有資料行都使用指向資料列值的頭指標) ,因此在本質上,使用固定長度的CHAR列不一定比使用可變長度的VARCHAR列效能要好。因而,主要的效能因素是資料行使用的儲存總量。由於CHAR平均佔用的空間多於VARCHAR,因此使用VARCHAR來最小化需要處理的資料行的儲存總量和磁碟I\O是比較好的。

5.5 列舉型別與集合型別

	欄位的值只能"在給定範圍中選擇",如單選框,多選框;	"enum" 單選,只能在給定的範圍內選一個值,如性別 sex 男male/女female	"set"  多選,在給定的範圍內可以選擇一個或一個以上的值(愛好1,愛好2,愛好3...) 
# 示例enum:mysql> create table shirts(    -> name varchar(40),    -> size enum('x-small', 'small', 'medium', 'large', 'x-large')    -> );# 正常插入值mysql> insert shirts(name,size) values('dress shirt','large'), ('t-shirt','medium'),('polo shirt','small');mysql> select * from shirts;+-------------+--------+| name        | size   |+-------------+--------+| dress shirt | large  || t-shirt     | medium || polo shirt  | small  |+-------------+--------+# 非正常插入值mysql> insert shirts values("abc shirts","xxxxxx");mysql> select * from shirts;+-------------+--------+| name        | size   |+-------------+--------+| dress shirt | large  || t-shirt     | medium || polo shirt  | small  || abc shirts  |        |+-------------+--------+  # 如果是嚴格模式,則會報錯,不允許傳入值;
# 示例:setmysql> create table user(    -> name varchar(16),    -> hobbies set("read","chou","drink","tang")    -> );# 正常傳值mysql> insert user values("xxx","tang,chou");mysql> select * from user;+------+-----------+| name | hobbies   |+------+-----------+| xxx  | chou,tang |+------+-----------+# 非正常傳值mysql> insert user values("qqq","tangchou");mysql> select * from user;+------+-----------+| name | hobbies   |+------+-----------+| xxx  | chou,tang || qqq  |           |+------+-----------+  # 非正常傳值,空

6 複製表

# 複製表結構+記錄(key不會複製:主鍵,外來鍵和索引) , # select語句查詢的內容儲存到表t2  全部複製將欄位改為*create table t2 select user,host,password from mysql.user;# 只複製表結構,# select語句查詢的表結構儲存到表t3  全部複製使用*create table t3 select user,host,password from mysql.user where 1!=1;
PS:關於"虛擬表":硬碟上不存在表,表存在於記憶體中,表是硬碟上資料的被select語句組織出來的。

7 刪除表

drop table 表名;

二 表操作之完整性約束

1 介紹

1.1 約束條件

#### 1 什麼是約束條件	約束條件與資料型別的寬度一樣,都是可選引數。#### 2 作用:	用於保證資料的完整性和一致性。

1.2 主要分類及說明:

PRIMARY KEY(PK)     # 標識該欄位為該表的主鍵,可以唯一的標識記錄FOREIGN KEY(FK)     # 標識該欄位為該表的外來鍵NOT NULL    		# 標識該欄位不能為空UNIQUE KEY(UK)		# 標識該欄位的值是唯一的AUTO_INCREMENT    	# 標識該欄位的值自動增長(整數型別,而且為主鍵) DEFAULT    			# 為該欄位設定預設值UNSIGNED    		# 無符號ZEROFILL    		# 使用0填充
1) 是否允許為空,預設NULL,可設定NOT NULL,欄位不允許為空,必須賦值;2) 欄位是否有預設值,預設的預設值是NULL,如果插入記錄時不給欄位賦值,此欄位使用預設值	sex enum('male','female') not null default 'male'	age int unsigned NOT NULL default 20  # 必須為正值(無符號)  不允許為空  預設是203) 是否是key主鍵  primary key外來鍵  foreign key索引  (index,unique...)

2 not null與default

	是否可空,null表示空,非字串。"not null"——>"不可空";"null"——>"可空"。	default是預設值,建立列時可以指定預設值,當插入資料時如果未主動設定,則自動新增預設值。
# 程式碼驗證==================not null====================mysql> create table t1(x int not null);  # 設定欄位id不為空mysql> desc t1;+-------+---------+------+-----+---------+-------+| Field | Type    | Null | Key | Default | Extra |+-------+---------+------+-----+---------+-------+| x     | int(11) | NO   |     | NULL    |       |+-------+---------+------+-----+---------+-------+mysql> insert t1 values();  # 不能插入空"""ERROR 1364 (HY000): Field 'x' doesn't have a default value"""==================default====================#設定id欄位有預設值後,則無論id欄位是null還是not null,都可以插入空,插入空預設填入default指定的預設值mysql> create table t2(x int not null default 666);mysql> insert t2 values();mysql> desc t2;+-------+---------+------+-----+---------+-------+| Field | Type    | Null | Key | Default | Extra |+-------+---------+------+-----+---------+-------+| x     | int(11) | NO   |     | 666     |       |+-------+---------+------+-----+---------+-------+mysql> select * from t2;+-----+| x   |+-----+| 666 |+-----+

3 unique

	unique是唯一約束,可以"單列唯一",也可以多個條件"聯合唯一"。

3.1 單列唯一

mysql> create table t3(name varchar(10) unique);mysql> insert t3 values("egon");mysql> insert t3 values("DSB");mysql> insert t2 values("DSB");ERROR 1366 (HY000): Incorrect integer value: 'DSB' for column 'x' at row 1

3.2 聯合唯一

mysql> create table server(    -> id int,    -> name varchar(10),    -> ip varchar(15),    -> port int,    -> unique(ip,port),    -> unique(name)    -> );mysql> desc server;+-------+-------------+------+-----+---------+-------+| Field | Type        | Null | Key | Default | Extra |+-------+-------------+------+-----+---------+-------+| id    | int(11)     | YES  |     | NULL    |       || name  | varchar(10) | YES  | UNI | NULL    |       || ip    | varchar(15) | YES  | MUL | NULL    |       || port  | int(11)     | YES  |     | NULL    |       |+-------+-------------+------+-----+---------+-------+mysql> insert server values (1,"web1","10.10.0.11",8080);mysql> insert server values (2,"web2","10.10.0.11",8081);mysql> insert server values(4,"web4","10.10.0.11",8081);-- ERROR 1062 (23000): Duplicate entry '10.10.0.11-8081' for key 'ip'mysql> insert server values(3,"網頁3","10.10.0.11",8082);mysql> select * from server;+------+---------+------------+------+| id   | name    | ip         | port |+------+---------+------------+------+|    1 | web1    | 10.10.0.11 | 8080 ||    2 | web2    | 10.10.0.11 | 8081 ||    3 | 網頁3   | 10.10.0.11 | 8082 |+------+---------+------------+------+

4 primary key

4.1 主鍵是什麼

	主鍵primary key是innodb儲存引擎組織資料的依據,innodb稱之為索引組織表。

4.2 特點:**

	一張innodb表中必須有且只有一個主鍵,可以:"單列做主鍵",也可以"多列做主鍵(複合/聯合主鍵) "。	主鍵的約束效果是not null + unique。

4.3 程式碼驗證

==================單列做主鍵==================# 方法一:在某一個欄位後用primary keymysql> create table t6(    -> id int primary key auto_increment, # 主鍵 # 不指定id,則自動增長    -> name varchar(5)    -> );mysql> insert t6(name) values    -> ("egon"),    -> ("is"),    -> ("DSB"),    -> ("DDB");mysql> desc t6;+-------+------------+------+-----+---------+----------------+| Field | Type       | Null | Key | Default | Extra          |+-------+------------+------+-----+---------+----------------+| id    | int(11)    | NO   | PRI | NULL    | auto_increment || name  | varchar(5) | YES  |     | NULL    |                |+-------+------------+------+-----+---------+----------------+mysql> select * from t6;+----+------+| id | name |+----+------+|  1 | egon ||  2 | is   |  # 儘量不要使用關鍵字作為表格的內容|  3 | DSB  ||  4 | DDB  |+----+------+# 方法二:not null+uniquemysql>  create table t6_2(    -> id int not null unique,  # 主鍵    -> name varchar(20) not null unique,    -> comment varchar(100)    -> );mysql> desc t6_2;+---------+--------------+------+-----+---------+-------+| Field   | Type         | Null | Key | Default | Extra |+---------+--------------+------+-----+---------+-------+| id      | int(11)      | NO   | PRI | NULL    |       || name    | varchar(20)  | NO   | UNI | NULL    |       || comment | varchar(100) | YES  |     | NULL    |       |+---------+--------------+------+-----+---------+-------+# 方法三:在所有欄位後單獨定義primary keymysql> create table t6_3(    -> id int,    -> name varchar(20),    -> comment varchar(100),    -> constraint pk_name primary key(id)  # 建立主鍵併為其命名pk_name    -> );mysql> desc t6_3;+---------+--------------+------+-----+---------+-------+| Field   | Type         | Null | Key | Default | Extra |+---------+--------------+------+-----+---------+-------+| id      | int(11)      | NO   | PRI | 0       |       || name    | varchar(20)  | YES  |     | NULL    |       || comment | varchar(100) | YES  |     | NULL    |       |+---------+--------------+------+-----+---------+-------+
==================多列做主鍵(瞭解) ==================mysql> create table t7(    -> id int,    -> name varchar(5),    -> primary key(id,name)    -> );mysql> desc t7;+-------+------------+------+-----+---------+-------+| Field | Type       | Null | Key | Default | Extra |+-------+------------+------+-----+---------+-------+| id    | int(11)    | NO   | PRI | 0       |       || name  | varchar(5) | NO   | PRI |         |       |+-------+------------+------+-----+---------+-------+

5 auto_increment

	約束欄位為自動增長,被約束的欄位必須同時被key約束。

6 foreign key

6.1 什麼是foreign key

	foreign key是外來鍵,用於關聯多張表,對錶進行解耦合,提高查詢速度。
1) # 先建立被關聯表mysql> create table dep(    -> id int primary key auto_increment,    -> name varchar(6),    -> comment varchar(60)    -> );    2) # 再建立關聯表mysql> create table emp(    -> id int primary key auto_increment,    -> name varchar(10),    -> gender varchar(5),    -> dep_id int,    -> foreign key(dep_id) references dep(id) on delete cascade on update cascade    -> );    3) # 先往被關聯表插入資料mysql> insert dep(id,name) values    -> (1,"技術部"),    -> (2,"人力資源部"),    -> (3,"銷售部");    mysql> desc dep;+---------+-------------+------+-----+---------+----------------+| Field   | Type        | Null | Key | Default | Extra          |+---------+-------------+------+-----+---------+----------------+| id      | int(11)     | NO   | PRI | NULL    | auto_increment || name    | varchar(6)  | YES  |     | NULL    |                || comment | varchar(60) | YES  |     | NULL    |                |+---------+-------------+------+-----+---------+----------------+mysql> select * from dep;+----+-----------------+---------+| id | name            | comment |+----+-----------------+---------+|  1 | 技術部          | NULL    ||  2 | 人力資源部      | NULL    ||  3 | 銷售部          | NULL    |+----+-----------------+---------+4) # 再往關聯表插入資料mysql> insert emp(name,gender,dep_id) values    -> ('egon',"male",1),    -> ('alex1',"male",2),    -> ('alex2',"male",2),    -> ('alex3',"male",2),    -> ('李坦克',"male",3),    -> ('劉飛機',"male",3),    -> ('張火箭',"male",3),    -> ('林子彈',"male",3),    -> ('加特林',"male",3);mysql> desc emp;+--------+-------------+------+-----+---------+----------------+| Field  | Type        | Null | Key | Default | Extra          |+--------+-------------+------+-----+---------+----------------+| id     | int(11)     | NO   | PRI | NULL    | auto_increment || name   | varchar(10) | YES  |     | NULL    |                || gender | varchar(5)  | YES  |     | NULL    |                || dep_id | int(11)     | YES  | MUL | NULL    |                |+--------+-------------+------+-----+---------+----------------+mysql> select * from emp;+----+-----------+--------+--------+| id | name      | gender | dep_id |+----+-----------+--------+--------+|  1 | egon      | male   |      1 ||  2 | alex1     | male   |      2 ||  3 | alex2     | male   |      2 ||  4 | alex3     | male   |      2 ||  5 | 李坦克    | male   |      3 ||  6 | 劉飛機    | male   |      3 ||  7 | 張火箭    | male   |      3 ||  8 | 林子彈    | male   |      3 ||  9 | 加特林    | male   |      3 |+----+-----------+--------+--------+

6.2 如何找出兩張表之間的關係

# 分析步驟1) 先站在左表的角度去找	是否左表的多條記錄可以對應右表的一條記錄,如果是,則證明左表的一個欄位foreign key 右表一個欄位(通常是id) 。    2) 再站在右表的角度去找	是否右表的多條記錄可以對應左表的一條記錄,如果是,則證明右表的一個欄位foreign key 左表一個欄位(通常是id) 。    3) 總結:# 多對一	如果只有步驟1成立,則是左表多對一右表;    如果只是步驟2成立,則是右表多對一左表。# 多對多	如果步驟1和2同時成立,則證明這兩張表同時一個雙向的多對一,即多對多,需要定義一個這兩張表的關係的關係表來專門存放二者的關係。# 一對一	如果1和2都不成立,而是左表的一條記錄唯一對應右表的一條記錄,反之亦然。這種情況很簡單,就是在左表foreign key 右表的基礎上,將左表的外來鍵欄位設定成unique即可。

6.3 建立表之間的關係

6.3.1 一對多或稱為多對一
三張表:出版社,作者,書一對多(或多對一) :一個出版社可以出版多本書關聯方式: foreign key
=====================多對一=====================mysql> create table press(    -> id int primary key auto_increment,    -> name varchar(20)    -> );mysql> create table book(    -> id int primary key auto_increment,    -> name varchar(20),    -> press_id int not null,    -> foreign key(press_id) references press(id) on delete cascade on update cascade    -> );mysql> insert press(name) values    -> ('醜國の音樂不好聽出版社'),    -> ('忒浪噗是個DSB出版社'),    -> ('啊醜離家出版社');mysql> insert book(name,press_id) values    -> ('九陽神功',1),    -> ('九陰真經',2),    -> ('九陰白骨爪',2),    -> ('獨孤九劍',3),    -> ('降龍十巴掌',2),    -> ('葵花寶典',3);mysql> select * from press;+----+--------------------------------+| id | name                           |+----+--------------------------------+|  1 | 醜國の音樂不好聽出版社           ||  2 | 忒浪噗是個DSB出版社              ||  3 | 啊醜離家出版社             |+----+--------------------------------+mysql> select * from book;+----+-----------------+----------+| id | name            | press_id |+----+-----------------+----------+|  1 | 九陽神功        |        1 ||  2 | 九陰真經        |        2 ||  3 | 九陰白骨爪      |        2 ||  4 | 獨孤九劍        |        3 ||  5 | 降龍十巴掌      |        2 ||  6 | 葵花寶典        |        3 |+----+-----------------+----------+
6.3.2 多對多
三張表:出版社,作者資訊,數多對多:一個作者可以寫多本書,一本書也可以有多個作者,雙向的一對多,即多對多關聯方式: foreign key + 一張新的表
=====================多對多=====================mysql> create table author(    -> id int primary key auto_increment,    -> name varchar(20)    -> );# 這張表就存放作者表與書表的關係,即查詢二者的關係查這表就可以了mysql> create table author2book(    -> id int not null unique auto_increment,    -> author_id int not null,    -> book_id int not null,    -> constraint fk_auther foreign key(author_id) references author(id) on delete cascade on update cascade,    -> constraint fk_book foreign key(book_id) references book(id) on delete cascade on update cascade,    -> primary key(auther_id,book_id)    -> );# 插入四個作者,id依次排開mysql> insert into author(name) values('egon'),('alex'),('yuanhao'),('wpq');# 每個作者與自己的代表作如下:1 egon:       1 九陽神功;2 九陰真經;3 九陰白骨爪;4 獨孤九劍;5 降龍十巴掌;6 葵花寶典;2 alex:       1 九陽神功;6 葵花寶典;3 yuanhao:      4 獨孤九劍;5 降龍十巴掌;6 葵花寶典;4 wpq:      1 九陽神功;mysql> insert into author2book(author_id,book_id) values    -> (1,1),    -> (1,2),    -> (1,3),    -> (1,4),    -> (1,5),    -> (1,6),    -> (2,1),    -> (2,6),    -> (3,4),    -> (3,5),    -> (3,6),    -> (4,1);    mysql> desc author2book;+-----------+---------+------+-----+---------+----------------+| Field     | Type    | Null | Key | Default | Extra          |+-----------+---------+------+-----+---------+----------------+| id        | int(11) | NO   | UNI | NULL    | auto_increment || author_id | int(11) | NO   | PRI | NULL    |                || book_id   | int(11) | NO   | PRI | NULL    |                |+-----------+---------+------+-----+---------+----------------+mysql> select * from author2book;+----+-----------+---------+| id | author_id | book_id |+----+-----------+---------+|  1 |         1 |       1 ||  2 |         1 |       2 ||  3 |         1 |       3 ||  4 |         1 |       4 ||  5 |         1 |       5 ||  6 |         1 |       6 ||  7 |         2 |       1 ||  8 |         2 |       6 ||  9 |         3 |       4 || 10 |         3 |       5 || 11 |         3 |       6 || 12 |         4 |       1 |+----+-----------+---------+
6.3.3 一對一
兩張表:學生表和客戶表一對一:一個學上是一個客戶,一個客戶有可能變成一個學生,即一對一的關係;關聯方式: foreign key + unique
# 一定是student來foreign key表customer,這樣就保證了:# 1 學生一定是一個客戶,# 2 客戶不一定是學生,但有可能成為一個學生
mysql> create table customer(    -> id int primary key auto_increment,    -> name varchar(20) not null,    -> qq varchar(10) not null,    -> phone char(16) not null    -> );mysql> create table student(    -> id int primary key auto_increment,    -> class_name varchar(20) not null,    -> customer_id int unique,  # 該欄位一定要是唯一的    -> foreign key(customer_id) references customer(id) on delete cascade on update cascade  # 外來鍵的欄位一定要保證unique    -> );# 增加客戶mysql> insert customer(name,qq,phone) values    -> ("x001",'100001','123123123'),    -> ("x002",'100002','123123124'),    -> ("x003",'100003','123123125');# 增加學生mysql> insert student(class_name,customer_id) values    -> ("linux",3),    -> ("go",1);    mysql> select * from customer;+----+------+--------+-----------+| id | name | qq     | phone     |+----+------+--------+-----------+|  1 | x001 | 100001 | 123123123 ||  2 | x002 | 100002 | 123123124 ||  3 | x003 | 100003 | 123123125 |+----+------+--------+-----------+mysql> select * from student;+----+------------+-------------+| id | class_name | customer_id |+----+------------+-------------+|  4 | linux      |           3 ||  5 | go         |           1 |+----+------------+-------------+