MySQL表相關操作
阿新 • • 發佈:2021-06-25
目錄
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 |+----+------------+-------------+