Python進階----數據庫引擎(InnoDB),表的創建,mysql的數據類型,mysql表的約束
一丶MySQL的存儲引擎
什么是存儲引擎:
MySQL中的數據用各種不同的技術存儲在文件(或者內存)中。這些技術中的每一種技術都使用不同的存儲機制、索引技巧、鎖定水平並且最終提供廣泛的不同的功能和能力。通過選擇不同的技術,你能夠獲得額外的速度或者功能,從而改善你的應用的整體功能。
例如,如果你在研究大量的臨時數據,你也許需要使用內存存儲引擎。內存存儲引擎能夠在內存中存儲所有的表格數據。又或者,你也許需要一個支持事務處理的數據庫(以確保事務處理不成功時數據的回退能力)。
這些不同的技術以及配套的相關功能在MySQL中被稱作存儲引擎(也稱作表類型)。
MySQL默認配置了許多不同的存儲引擎,可以預先設置或者在MySQL服務器中啟用。你可以選擇適用於服務器、數據庫和表格的存儲引擎,以便在選擇如何存儲你的信息、如何檢索這些信息以及你需要你的數據結合什么性能和功能的時候為你提供最大的靈活性。
選擇如何存儲和檢索你的數據的這種靈活性是MySQL為什么如此受歡迎的主要原因。其它數據庫系統(包括大多數商業選擇)僅支持一種類型的數據存儲。
遺憾的是,其它類型的數據庫解決方案采取的“一個尺碼滿足一切需求”的方式意味着你要么就犧牲一些性能,要么你就用幾個小時甚至幾天的時間詳細調整你的數據庫。使用MySQL,我們僅需要修改我們使用的存儲引擎就可以了
存儲引擎:存儲文件的一種方式,不同的存儲引擎存儲數據是不同的.
myql默認支持哪些引擎:
mysql5.6支持的存儲引擎包括InnoDB、MyISAM、MEMORY、CSV、BLACKHOLE、FEDERATED、MRG_MYISAM、ARCHIVE、PERFORMANCE_SCHEMA。其中NDB和InnoDB提供事務安全表,其他存儲引擎都是非事務安全表。
查看所有mysql所有引擎:
各種引擎的介紹:👇
# InnoDB
MySql 5.6 版本默認的存儲引擎。InnoDB 是一個事務安全的存儲引擎,它具備提交、回滾以及崩潰恢復的功能以保護用戶數據。InnoDB 的行級別鎖定以及 Oracle 風格的一致性無鎖讀提升了它的多用戶並發數以及性能。InnoDB 將用戶數據存儲在聚集索引中以減少基於主鍵的普通查詢所帶來的 I/O 開銷。為了保證數據的完整性,InnoDB 還支持外鍵約束。
# MyISAM
MyISAM既不支持事務、也不支持外鍵、其優勢是訪問速度快,但是表級別的鎖定限制了它在讀寫負載方面的性能,因此它經常應用於只讀或者以讀為主的數據場景。
# Memory
在內存中存儲所有數據,應用於對非關鍵數據由快速查找的場景。Memory類型的表訪問數據非常快,因為它的數據是存放在內存中的,並且默認使用HASH索引,但是一旦服務關閉,表中的數據就會丟失
# BLACKHOLE
黑洞存儲引擎,類似於 Unix 的 /dev/null,Archive 只接收但卻並不保存數據。對這種引擎的表的查詢常常返回一個空集。這種表可以應用於 DML 語句需要發送到從服務器,但主服務器並不會保留這種數據的備份的主從配置中。
# CSV
它的表真的是以逗號分隔的文本文件。CSV 表允許你以 CSV 格式導入導出數據,以相同的讀和寫的格式和腳本和應用交互數據。由於 CSV 表沒有索引,你最好是在普通操作中將數據放在 InnoDB 表里,只有在導入或導出階段使用一下 CSV 表。
# NDB
(又名 NDBCLUSTER)——這種集群數據引擎尤其適合於需要最高程度的正常運行時間和可用性的應用。注意:NDB 存儲引擎在標准 MySql 5.6 版本里並不被支持。目前能夠支持
MySql 集群的版本有:基於 MySql 5.1 的 MySQL Cluster NDB 7.1;基於 MySql 5.5 的 MySQL Cluster NDB 7.2;基於 MySql 5.6 的 MySQL Cluster NDB 7.3。同樣基於 MySql 5.6 的 MySQL Cluster NDB 7.4 目前正處於研發階段。
# Merge
允許 MySql DBA 或開發者將一系列相同的 MyISAM 表進行分組,並把它們作為一個對象進行引用。適用於超大規模數據場景,如數據倉庫。
# Federated
提供了從多個物理機上聯接不同的 MySql 服務器來創建一個邏輯數據庫的能力。適用於分布式或者數據市場的場景。
# Example
這種存儲引擎用以保存闡明如何開始寫新的存儲引擎的 MySql 源碼的例子。它主要針對於有興趣的開發人員。這種存儲引擎就是一個啥事也不做的 "存根"。你可以使用這種引擎創建表,但是你無法向其保存任何數據,也無法從它們檢索任何索引。
存儲引擎的特性:
1.並發性:開發某些程序比其應用程序具有很多的顆粒劑鎖定要求(行級鎖)
2.事務支持性:並非所有的應用程序都需要事務,但對需要事務的應用來說,有着定義良好的需求
3.引用完整性:通過DDL定義的外鍵,服務器需要強制保持關聯數據庫的引用完整性
4.物理存儲:包括各種的事項,從表的索引的總的頁大小,到存儲數據所需的格式,到物理磁盤
5.索引支持:不同的應用程序更傾向於采用不同的索引策略,每種存儲引擎通常有自己的編制索引的方式.但某些索引方法(如B-tree索引)對幾乎所有的存儲引擎來說是共同的
6.內存高速緩沖:與其他應用程序相比,不同的應用程序對某些內存高速緩沖策略的響應更好,因此,,盡管某些內存高速緩沖對所有存儲引擎來說是共同的(如:用戶連接高速緩沖,mysql的高速查詢高速緩沖等.),其他高速緩沖策略僅當使用特殊的存儲引擎時才唯一定義
7.性能幫助:針對並行操作的多I/O線程,線程並發性.數據庫檢查點,成批插入等
8.其他目標特性:可能包括對地理空間操作的支持,對特定數據處理操作的安全限制等.
#以上要求會在不同的需求中予以體現,通過單獨一個系統實現是不可能的,以上特點有些本身就是相互矛盾的,魚和熊掌的問題。對以上內容做些選擇,形成的存儲引擎就是一個插件引擎了,某些特定的需求可以使用
mysql常用的存儲引擎:
InnoDB應用場景及特點:
用於事務處理應用程序,支持外鍵和行級鎖.如果應用對事務的完整性有比較高的要求,在並發條件下要求數據的一致性,數據操作除了插入和查詢之外,還包括很多更新和刪除操作,使用InnoDB存儲引擎是比較合適的.InnoDB除了有效的降低由刪除和更新導致的鎖定,還可確保事務的完整提交和回滾,對於類似計費系統或者財務系統等對數據准確要求性比較高的系統都是適合的選擇.
### InnoDB的縮略特點:如下👇
# 2個文件夾(.frm存放表結構 , .ibd存放數據)
# mysql5.6以上 默認的存儲方式
# transaction 事務 保證數據安全 數據的完整性而設置的概念
# row-level locking 行級鎖
# table-level locking 表級鎖
# foreign keys 外鍵約束
# 樹tree - 加速查詢 (樹形結構(數據+樹) + 表結構)
# 創建 engine引擎為InnoDB的數據表
create table Innodb_t (id int,name char(18)) engine=InnoDB;
# 查看表結構
show create table innodb_t;
# 結果: ENGINE=InnoDB
MyISAM應用場景和特點:
是以讀操作和插入操作為主,只有很少的更新和刪除操作,並且對事務的完整性、並發性要求不太高
### 縮略特點:
# 3個文件夾(.frm存放表結構 , .MYD存放數據, .MYI存放樹形結構)
# mysql5.5以下 默認的存儲方式
# table-level locking 表級鎖
# 樹tree - 加速查詢 (樹形結構 + 數據 + 表結構)
# 創建 engine引擎為mysiam的數據表
create table myisam_t (id int,name char(18)) engine=myisam
# 查看表結構
show create table myisam_t;
# 結果: ENGINE=MyISAM
Memory:
將所有的數據保存在內存中,在需要快速定位記錄和其他類似數據的環境下,可以提供極快的訪問。Memory的缺陷是對表的大小有限制,雖然數據庫因為異常終止的話數據可以正常恢復,但是一旦數據庫關閉,存儲在內存中的數據都會丟失。
### 縮略特點:
# 1個文件夾(.frm存放表結構 ) ,數據放在內存中
# 基於hash
# 創建 engine引擎為memory的數據表
create table memory_t (id int,name char(18)) engine=memory;
# 查看表結構
show create table memory_t;
# 結果: ENGINE=MEMORY
修改表引擎:
# 修改表引擎
alter table memory_t engine = innodb;
# 查看結果
show create table memory_t;
文件形式配置引擎:
#my.ini文件
[mysqld]
default-storage-engine=INNODB
mysql工作流程:
MySQL架構總共四層,在上圖中以虛線作為划分。
首先,最上層的服務並不是MySQL獨有的,大多數給予網絡的客戶端/服務器的工具或者服務都有類似的架構。比如:連接處理、授權認證、安全等。
第二層的架構包括大多數的MySQL的核心服務。包括:查詢解析、分析、優化、緩存以及所有的內置函數(例如:日期、時間、數學和加密函數)。同時,所有的跨存儲引擎的功能都在這一層實現:存儲過程、觸發器、視圖等。
第三層包含了存儲引擎。存儲引擎負責MySQL中數據的存儲和提取。服務器通過API和存儲引擎進行通信。這些接口屏蔽了不同存儲引擎之間的差異,使得這些差異對上層的查詢過程透明化。存儲引擎API包含十幾個底層函數,用於執行“開始一個事務”等操作。但存儲引擎一般不會去解析SQL(InnoDB會解析外鍵定義,因為其本身沒有實現該功能),不同存儲引擎之間也不會相互通信,而只是簡單的響應上層的服務器請求。
第四層包含了文件系統,所有的表結構和數據以及用戶操作的日志最終還是以文件的形式存儲在硬盤上
二丶表的操作
創建表語法:
#語法:
create table 表名(
字段名1 類型[(寬度) 約束條件],
字段名2 類型[(寬度) 約束條件],
字段名3 類型[(寬度) 約束條件]
);
#注意:
1. 在同一張表中,字段名是不能相同
2. 寬度和約束條件可選
3. 字段名和類型是必須的
創建表和查看表結構:
######## cmd 命令行模式執行👇:
# 1. 創建數據庫
create database staff;
# 2. 使用數據庫
use staff
# 3. 創建表
create table staff_info (
id int,name varchar(50),
age int(3),
sex enum('male','female'),
phone bigint(11),
job varchar(11)
);
# 4. 查看表結構
desc staff_info
# 5. 增加數據
insert into staff_info (id,name,age,sex,phone,job) values (1,'lisi',83,'female',13651054608,'IT');
# 6. 查詢數據
select * from staff_info;
三丶MySQL中常用的數據類型
數值類型:
常用數值類型:tinyin , int 和 float(四舍五入)
類型 | 大小 | 范圍(有符號) | 范圍(無符號)unsigned約束 | 用途 |
---|---|---|---|---|
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 字節float(255,30) | (-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 字節double(255,30) | (-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+2double(65,30) | 依賴於M和D的值 | 依賴於M和D的值 | 小數值 |
int類型實例:
# 1. 創建一個t1表
create table t1(id1 int ,id2 int(5));
# 2. 查看 t1 表結構 , int默認給11個寬度 , 但與實際可存的值不一樣.
desc t1;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id1 | int(11) | YES | | NULL | |
| id2 | int(5) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
select * from t1;
+------------+--------+
| id1 | id2 |
+------------+--------+
| 0000000001 | 00001 |
| 0000111111 | 111111 |
+------------+--------+
# 3.增加數據.
mysql> insert into t1 values(111111,11111111);
# 4.t1表 id1 字段 修改 添加unsigned無符號約束
mysql> alter table t1 modify id1 int unsigned;
# 結果:
Query OK, 5 rows affected (0.70 sec)
Records: 5 Duplicates: 0 Warnings: 0
# 5. 再次查看表結構
mysql> desc t1;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id1 | int(10) unsigned | YES | | NULL | |
| id2 | int(5) | YES | | NULL | |
+-------+------------------+------+-----+---------+-------+
# 6. 再次添加數據, 無符號unsigned修飾的id1可存4294967295
mysql> insert into t1(id1) values (4294967295);
mysql> select * from t1;
+------------+------------+
| id1 | id2 |
+------------+------------+
| 4294967295 | NULL |
+------------+------------+
# 7. 有符號的只能存 -2147483648 ~ +2147483647
mysql> insert into t1 values(-2147483648,2147483647);
Query OK, 1 row affected (0.12 sec)
mysql> insert into t1 values(-2147483649,2147483647);
ERROR 1264 (22003): Out of range value for column 'id1' at row 1
mysql> insert into t1 values(-2147483648,2147483648);
ERROR 1264 (22003): Out of range value for column 'id2' at row 1
mysql>
小數實例:
float(5,2):表示一共5位,小數點后保留2位
# 1 .創建t2表 float double decimal 三個字段
mysql> create table t2 (id1 float(5,2),id2 double(5,2),id3 decimal(5,2));
Query OK, 0 rows affected (0.34 sec)
# 2 .查看表結構
mysql> desc t2;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id1 | float(5,2) | YES | | NULL | |
| id2 | double(5,2) | YES | | NULL | |
| id3 | decimal(5,2) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
# 3.添加數據
mysql> insert into t2 values (1.234567,1.234567,1.234567);
Query OK, 1 row affected, 1 warning (0.12 sec)
# 不難發現都被截斷了. (5,2)表示一共5位,小數點后保留2位,剩余的3位是小數點前
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
+------+------+------+
1 row in set (0.00 sec)
# 4. 四舍五入 小數點后兩位保留,根據下一位進項四舍五入
mysql> insert into t2 values (1.235567,1.235567,1.235567);
Query OK, 1 row affected, 1 warning (0.11 sec)
mysql> select * from t2;
+------+------+------+
| id1 | id2 | id3 |
+------+------+------+
| 1.23 | 1.23 | 1.23 |
| 1.24 | 1.24 | 1.24 |
+------+------+------+
2 rows in set (0.00 sec)
# 5. 去掉約束創建t3表 , decimal默認是(10,0)
mysql> create table t3 (id1 float,id2 double,id3 decimal);
Query OK, 0 rows affected (0.32 sec)
mysql> desc t3;
+-------+---------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------------+------+-----+---------+-------+
| id1 | float | YES | | NULL | |
| id2 | double | YES | | NULL | |
| id3 | decimal(10,0) | YES | | NULL | |
+-------+---------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
# 6. decimal默認取整
mysql> insert into t3 values (1.234,1.234,1.234);
Query OK, 1 row affected, 1 warning (0.12 sec)
mysql> select * from t3;
+-------+-------+------+
| id1 | id2 | id3 |
+-------+-------+------+
| 1.234 | 1.234 | 1 |
+-------+-------+------+
1 row in set (0.00 sec)
# 7. 當對小數位沒有約束的時候,輸入超長的小數,會發現float和double的區別
# float默認保留6位
# double默認保留17位
mysql> insert into t3 values (1.2355555555555555555,1.2355555555555555555,1.2355555555555555555555);
Query OK, 1 row affected, 1 warning (0.11 sec)
mysql> select * from t3;
+---------+--------------------+------+
| id1 | id2 | id3 |
+---------+--------------------+------+
| 1.234 | 1.234 | 1 |
| 1.23556 | 1.2355555555555555 | 1 |
+---------+--------------------+------+
2 rows in set (0.00 sec)
時間日期類型
常用: date
類型 | 大小 (字節) | 范圍 | 格式 | 用途 | 應用場景 |
---|---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 年月日 | 員工生日 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 時分秒 | 每天固定某一時刻的任務 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 | 年份(酒年份) |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 年月日時分秒 | 日志/博客評論 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038結束時間是第 2147483647 秒,北京時間 2038-1-19 11:14:07,格林尼治時間 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和時間值,時間戳 | 范圍只能到2038年,使用少 |
日期案例:
# 1. 創建 t4表, 存放各種日期類型
mysql> create table t4(d date ,t time ,dt datetime,y year,ts timestamp);
mysql> desc t4;
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-----------+------+-----+-------------------+-----------------------------+
| d | date | YES | | NULL | |
| t | time | YES | | NULL | |
| dt | datetime | YES | | NULL | |
| y | year(4) | YES | | NULL | |
| ts | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+-----------+------+-----+-------------------+-----------------------------+
5 rows in set (0.01 sec)
# 2. 添加數據 now()聚合函數,由mysql數據庫提供,獲取當前時間.
## timestamp 類型的數據 被約束了, 默認獲取當前時間,不能為空
## ts字段 插入數據null,會自動插入當前時間的時間
## 其他類型的數據 按照類型截取自己需要的時間.
mysql> insert into t4 values (now(),now(),now(),now(),null );
Query OK, 1 row affected, 1 warning (0.11 sec)
mysql> select * from t4;
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| 2019-07-30 | 17:28:11 | 2019-07-30 17:28:11 | 2019 | 2019-07-30 17:28:11 |
+------------+----------+---------------------+------+---------------------+
1 row in set (0.00 sec)
# 3. 手動添加datetime數據類型
#格式: 2018-9-26 12:20:10 或者,2018/9/26 12+20+10 或者,20180926122010 或者,20180926122010
mysql> insert into t4(dt) values (20180926122010);
mysql> insert into t4(dt) values ('2018/9/26 12+20+10');
mysql> insert into t4(dt) values ('2018-9-26 12:20:10');
mysql> select * from t4;
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| 2019-07-30 | 17:28:11 | 2019-07-30 17:28:11 | 2019 | 2019-07-30 17:28:11 |
| NULL | NULL | 2018-09-26 12:20:10 | NULL | 2019-07-30 17:35:00 |
| NULL | NULL | 2018-09-26 12:20:10 | NULL | 2019-07-30 17:35:21 |
| NULL | NULL | 2018-09-26 12:20:10 | NULL | 2019-07-30 17:35:53 |
+------------+----------+---------------------+------+---------------------+
# 但是 數值類型的長度必須是20180926122010 14位, 少一位都不行
mysql> insert into t4(dt) values (2018092612201);
ERROR 1292 (22007): Incorrect datetime value: '2018092612201' for column 'dt' at row 1
# 字符串不限制,默認為0
mysql> insert into t4(dt) values ('2018-9-26 12:20');
mysql> select * from t4;
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| NULL | NULL | 2018-09-26 12:20:00 | NULL | 2019-07-30 17:38:40 |
+------------+----------+---------------------+------+---------------------+
# 4. 修改某條記錄時,timestamp自動更新
mysql> select * from t4;
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| 2019-07-30 | 17:28:11 | 2019-07-30 17:28:11 | 2019 | 2019-07-30 17:28:11 |
+------------+----------+---------------------+------+---------------------+
Query OK, 1 row affected (0.12 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 查看數據,發現字段 ts是timestamp 類型數據 時間被更新了.
mysql> select * from t4;
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| 2019-07-30 | 17:28:11 | 2019-07-30 17:28:11 | 2020 | 2019-07-30 17:48:06 |
+------------+----------+---------------------+------+---------------------+
原因: 對 ts字段 做了約束(NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP)
mysql> show create table t4;
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t4 | CREATE TABLE `t4` (
`d` date DEFAULT NULL,
`t` time DEFAULT NULL,
`dt` datetime DEFAULT NULL,
`y` year(4) DEFAULT NULL,
`ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
# 5. 手動添加data數據類型
mysql> insert into t4(d) values ('2018-12-12');
Query OK, 1 row affected (0.11 sec)
# 但只截取 年月日
mysql> insert into t4(d) values ('2018-12-12 12:12:12');
Query OK, 1 row affected, 1 warning (0.04 sec)
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| 2018-12-12 | NULL | NULL | NULL | 2019-07-30 17:45:04 |
| 2018-12-12 | NULL | NULL | NULL | 2019-07-30 17:45:12 |
+------------+----------+---------------------+------+---------------------+
# 6. 手動添加year數據類型
mysql> insert into t4(y) values ('2018');
mysql> select * from t4;
+------------+----------+---------------------+------+---------------------+
| d | t | dt | y | ts |
+------------+----------+---------------------+------+---------------------+
| NULL | NULL | NULL | 2018 | 2019-07-30 17:41:12 |
+------------+----------+---------------------+------+---------------------+
字符串類型
定義:
CHAR 和 VARCHAR 類型類似,但它們保存和檢索的方式不同。它們的最大長度和是否尾部空格被保留等方面也不同。在存儲或檢索過程中不進行大小寫轉換。
char 占據空間,效率高, varchar 采用n+1的模式,1為存放字符的個數多少個.不占空間,相對效率低
類型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255字節 | 定長字符串 |
VARCHAR | 0-65535 字節 | 變長字符串 |
TINYBLOB | 0-255字節 | 不超過 255 個字符的二進制字符串 |
TINYTEXT | 0-255字節 | 短文本字符串 |
BLOB | 0-65 535字節 | 二進制形式的長文本數據 |
TEXT | 0-65 535字節 | 長文本數據 |
MEDIUMBLOB | 0-16 777 215字節 | 二進制形式的中等長度文本數據 |
MEDIUMTEXT | 0-16 777 215字節 | 中等長度文本數據 |
LONGBLOB | 0-4 294 967 295字節 | 二進制形式的極大文本數據 |
LONGTEXT | 0-4 294 967 295字節 | 極大文本數據 |
char和varchar案例:
# 1. 創建 t5 表, 並 查詢表結構, 不難發現 char默認是1個字符
## char的長度是0-255字符, varchar的長度是0-65535個字符.
mysql> create table t5(c1 char, c2 char(5), vc varchar(5));
Query OK, 0 rows affected (0.30 sec)
mysql> desc t5;
+-------+------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------+------+-----+---------+-------+
| c1 | char(1) | YES | | NULL | |
| c2 | char(5) | YES | | NULL | |
| vc | varchar(5) | YES | | NULL | |
+-------+------------+------+-----+---------+-------+
# 2. 增加數據
# 字符
mysql> insert into t5 values('a','abcd','abcd');
## 支持 中文
mysql> insert into t5 values('你','歡迎你啊親','歡迎你啊秦');
mysql> select * from t5;
+------+-----------------+-----------------+
| c1 | c2 | vc |
+------+-----------------+-----------------+
| a | abcd | abcd |
| 你 | 歡迎你啊親 | 歡迎你啊秦 |
+------+-----------------+-----------------+
## 錯誤 , 原因: 增加的字符長度不能炒鍋設定長度.
mysql> insert into t5 values('abcdef','abcdef','abcdef');
ERROR 1406 (22001): Data too long for column 'c1' at row 1
mysql> insert into t5 values('a','abcdef','abcdef');
ERROR 1406 (22001): Data too long for column 'c2' at row 1
mysql> insert into t5 values('a','abcd5','abcdef');
ERROR 1406 (22001): Data too long for column 'vc' at row 1
mysql> insert into t5 values('a','abcd','abcdef');
ERROR 1406 (22001): Data too long for column 'vc' at row 1
# 3. char添加的時候回自動去除兩端的空格, varchar不會去空格
mysql> insert into t5 values('a','ab ','ab '); # char(c2):2 varchar(vc):4
mysql> insert into t5 values('a','a b ','ab '); # char(c2):3 varchar(vc):4
# 查看長度
mysql> select length(c2) ,length(vc) from t5;
+------------+------------+
| length(c2) | length(vc) |
+------------+------------+
| 2 | 4 |
| 3 | 4 |
+------------+------------+
# 給查詢的拼接上 + 號
mysql> select concat(c2,'+'),concat(vc,'+') from t5;
+------------------+------------------+
| concat(c2,'+') | concat(vc,'+') |
+------------------+------------------+
| ab+ | ab + |
| a b+ | ab + |
+------------------+------------------+
# 4. 存儲長度超過定義長度 ,會截斷
mysql> insert into t5 values('a','abcde ','abcde ');
Query OK, 1 row affected, 1 warning (0.11 sec)
mysql> insert into t5 values('a','abcde ','abcde ');
Query OK, 1 row affected, 1 warning (0.03 sec)
mysql> select length(c2) ,length(vc) from t5;
+------------+------------+
| length(c2) | length(vc) |
+------------+------------+
| 5 | 5 |
| 5 | 5 |
+------------+------------+
ENUM和SET類型
定義:
ENUM中文名稱叫枚舉類型,它的值范圍需要在創建表時通過枚舉方式顯示。ENUM只允許從值集合中選取單個值,而不能一次取多個值。
SET和ENUM非常相似,也是一個字符串對象,里面可以包含0-64個成員。根據成員的不同,存儲上也有所不同。set類型可以允許值集合中任意選擇1或多個元素進行組合。對超出范圍的內容將不允許注入,而對重復的值將進行自動去重。
類型 | 大小 | 用途 |
---|---|---|
ENUM | 對1-255個成員的枚舉需要1個字節存儲;對於255-65535個成員,需要2個字節存儲;最多允許65535個成員。 | 單選:選擇性別 |
SET | 1-8個成員的集合,占1個字節9-16個成員的集合,占2個字節17-24個成員的集合,占3個字節25-32個成員的集合,占4個字節33-64個成員的集合,占8個字節 | 多選:興趣愛好 |
set/enum案例
# 1. 創建 t6表, gender 字段 enum數據類 ,查勘表結構
mysql> create table t6 (name char(20) ,gender enum('男','女'));
Query OK, 0 rows affected (0.32 sec)
mysql> desc t6;
+--------+-------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------+------+-----+---------+-------+
| name | char(20) | YES | | NULL | |
| gender | enum('男','女') | YES | | NULL | |
+--------+-------------------+------+-----+---------+-------+
# 2. t6表, gender 增加數據
# enum 是單選 ,enum('男','女') 只能選擇一個項添加到數據庫
mysql> insert into t6 values('alex','男');
mysql> select * from t6;
+------+--------+
| name | gender |
+------+--------+
| alex | 男 |
+------+--------+
# 錯誤示例 不能同時插入'男','女'兩個值,也不能插入不屬於'男','女'的值
mysql> insert into t6 values('alexsb','男,女');
ERROR 1265 (01000): Data truncated for column 'gender' at row 1
# 3. 創建 t7 表, 設置hobby字段 是set類型 ,可多選
mysql> create table t7 (name char(20),hobby set('抽煙','喝酒','燙頭','翻車'));
Query OK, 0 rows affected (0.26 sec)
# 4. t7 表 ,hobby字段可多選, 並自帶去重功能
mysql> insert into t7 values('lisi','抽煙,喝酒,喝酒,喝酒');
# 查看t7表數據
mysql> select * from t7;
+------+---------------+
| name | hobby |
+------+---------------+
| lisi | 抽煙,喝酒 |
+------+---------------+
# 錯誤實例 ,爬山不在設定的hobby字段內.
mysql> insert into t7 values('lisi','抽煙,喝酒,喝酒,喝酒,爬山');
ERROR 1265 (01000): Data truncated for column 'hobby' at row 1
四丶mysql中的表的約束
約束種類:
# unsigned : 無符號 ,適用於數值型
# NOT NULL :非空約束,指定某列不能為空;
# UNIQUE : 唯一約束,指定某列或者幾列組合不能重復
# PRIMARY KEY :主鍵約束,指定該列的值可以唯一地標識該列記錄
# FOREIGN KEY :外鍵約束,指定該行記錄從屬於主表中的一條記錄,主要用於參照完整性
# default : 設置默認值
# auto_increment : 自增
Not null 非空約束:
含義: 表示這個字段在增加時,不能為空
# 1. 創建表 t8 指定id字段不能為空
mysql> create table t8(id int not null);
Query OK, 0 rows affected (0.32 sec)
# 2. t8表 增加數據
# 錯誤 1:
mysql> insert into t8 values();
ERROR 1364 (HY000): Field 'id' doesn't have a default value
# 錯誤 2: 由於id字段設置了不為空,
mysql> insert into t8 values(null);
ERROR 1048 (23000): Column 'id' cannot be null
# 必須填寫數據,才能插入成功
mysql> insert into t8 values(1);
Query OK, 1 row affected (0.12 sec)
# 查詢表結果
mysql> select * from t8;
+----+
| id |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
設置not null生效:嚴格模式
設置嚴格模式:
不支持對not null字段插入null值
不支持對自增長字段插入”值
不支持text字段有默認值
直接在mysql中生效(重啟失效):
mysql>set sql_mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";
配置文件添加(永久失效):
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
DEFAULT 默認值約束:
含義:
我們約束某一列不為空,如果這一列中經常有重復的內容,就需要我們頻繁的插入,這樣會給我們的操作帶來新的負擔,於是就出現了默認值的概念。
默認值,創建列時可以指定默認值,當插入數據時如果未主動設置,則自動添加默認值
#1. 創建表 t9 設置id1 字段不為空, id2字段默認值222
mysql> create table t13 (id1 int not null,id2 int not null default 222);
#查看表結構
mysql> desc t9;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id1 | int(11) | NO | | NULL | |
| id2 | int(11) | NO | | 222 | |
+-------+---------+------+-----+---------+-------+
# 2. t9表添加數據, 只向id1字段添加值,會發現id2字段會使用默認值填充
mysql> insert into t9 (id1) values (111);
mysql> select * from t13;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 111 | 222 |
+-----+-----+
# 3. t9表添加數據, id1字段不能為空,所以不能單獨向id2字段填充值;
mysql> insert into t13 (id2) values (223);
ERROR 1364 (HY000): Field 'id1' doesn't have a default value
# 4. t9表添加數據, 向id1,id2中分別填充數據,id2的填充數據會覆蓋默認值
mysql> insert into t13 (id1,id2) values (112,223);
mysql> select * from t13;
+-----+-----+
| id1 | id2 |
+-----+-----+
| 111 | 222 |
| 112 | 223 |
+-----+-----+
UNIQUE 唯一約束:
含義:
唯一約束,指定某列或者幾列組合不能重復
不允許重復插入相同的值. 當值為null時,可以重復插入.
UNIQUE案例:
# 方法一:
create table department1(
id int,
name varchar(20) unique,
comment varchar(100)
);
# 方法二:
create table department2(
id int,
name varchar(20),
comment varchar(100),
unique(name)
);
mysql> insert into department1 values(1,'IT','技術');
Query OK, 1 row affected (0.00 sec)
mysql> insert into department1 values(1,'IT','技術');
ERROR 1062 (23000): Duplicate entry 'IT' for key 'name'
UNIQUE + NOT NULL = primary key
#### 唯一約束 + 非空約束 = 主鍵約束
# 1. 創建表 t11 設置 非空+唯一
mysql> create table t11(id int not null unique);
Query OK, 0 rows affected (0.02 sec)
# 2. 查看表結構
mysql> desc t11;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
+-------+---------+------+-----+---------+-------+
row in set (0.00 sec)
聯合唯一:
# 1 .創建service表, host和port 字段聯合唯一
mysql> create table service(
id int primary key auto_increment,
name varchar(20),
host varchar(15) not null,
port int not null,
unique(host,port) # 聯合唯一
);
# 查看表結構
mysql> desc service;
+-------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| host | varchar(15) | NO | MUL | NULL | |
| port | int(11) | NO | | NULL | |
+-------+-------------+------+-----+---------+----------------+
# 2 .插入數據
mysql> insert into service values
(1,'nginx','192.168.0.10',80),
(2,'haproxy','192.168.0.20',80),
(3,'mysql','192.168.0.30',3306);
Query OK, 3 rows affected (0.12 sec)
Records: 3 Duplicates: 0 Warnings: 0
# 查詢結果
mysql> select * from service;
+----+---------+--------------+------+
| id | name | host | port |
+----+---------+--------------+------+
| 1 | nginx | 192.168.0.10 | 80 |
| 2 | haproxy | 192.168.0.20 | 80 |
| 3 | mysql | 192.168.0.30 | 3306 |
+----+---------+--------------+------+
# 3. 再次添加數據, port 和 host 已經存在相同的, 報錯
mysql> insert into service(name,host,port) values('nginx','192.168.0.10',80);
ERROR 1062 (23000): Duplicate entry(重復條目) '192.168.0.10-80' for key 'host'
PRIMARY KEY 主鍵約束:
含義:
主鍵為了保證表中的每一條數據的該字段都是表格中的唯一值. 它是用來確定表中的每一行數據都是唯一的存在
主鍵可以設置一個字段或多個字段,當主鍵包含多個欄位時,成為聯合主鍵.
設置主鍵時必須唯一 + 非空, 但至少設置主鍵非空unique.
單字段主鍵:
# 1. 創建表 tb1 字段id 被約束成主鍵
mysql> create table tb1(id int primary key);
Query OK, 0 rows affected (0.33 sec)
# 2. 查看表tb1 結構
mysql> desc tb1;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
+-------+---------+------+-----+---------+-------+
1 row in set (0.01 sec)
# 3.增加有值數據
mysql> insert into tb1 values(1);
Query OK, 1 row affected (0.04 sec)
# 4.增加null數據,報錯. 不允許增加null數據
mysql> insert into tb1 values(null);
ERROR 1048 (23000): Column 'id' cannot be null
# 5. 創建一個沒有主鍵約束的tb2表,
mysql> create table tb2(id int);
Query OK, 0 rows affected (0.34 sec)
# 查看tb2表結構 ,可以看出 沒有主鍵約束,存值時可以為空
mysql> desc tb2;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
# 6. 對tb2表的id字段進行主鍵約束修改
mysql> alter table tb2 modify id int primary key;
Query OK, 0 rows affected (0.54 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 查看tb2表結構,不難發現 id字段被附上了主鍵約束,存值時不能為空
mysql> desc tb2;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| id | int(11) | NO | PRI | NULL | |
+-------+---------+------+-----+---------+-------+
多字段主鍵:
# 1 . 創建表tb3 ip字段和port字段 設置成聯合主鍵
create table tb3(id int not null ,
name char(5),
ip char(15),
port int,
primary key(ip,port) # ip和port 字段設置成聯合主鍵
);
# 2. 查看表結構,不難發現 ip和port都具有了主鍵約束
mysql> desc tb3;
+-------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+----------+------+-----+---------+-------+
| id | int(11) | NO | | NULL | |
| name | char(5) | YES | | NULL | |
| ip | char(15) | NO | PRI | | |
| port | int(11) | NO | PRI | 0 | |
+-------+----------+------+-----+---------+-------+
# 3.插入數據
mysql> insert into tb3 values(1,'ftp','10.10.1.1',8848);
Query OK, 1 row affected (0.12 sec)
# 查看結果
mysql> select * from tb3;
+----+------+-----------+------+
| id | name | ip | port |
+----+------+-----------+------+
| 1 | ftp | 10.10.1.1 | 8848 |
+----+------+-----------+------+
1 row in set (0.00 sec)
# 4. 插入相同的數據會報錯,由於約束原因,只能存在一個ip和port
mysql> insert into tb3 values(1,'ftp','10.10.1.1',8848);
ERROR 1062 (23000): Duplicate entry '10.10.1.1-8848' for key 'PRIMARY'
# 5. 查看表tb3 的詳細結構 show create table tb3;
mysql> show create table tb3;
| tb3 | CREATE TABLE `tb3` (
`id` int(11) NOT NULL,
`name` char(5) DEFAULT NULL,
`ip` char(15) NOT NULL DEFAULT '',
`port` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ip`,`port`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
auto_increment 自增約束:
含義:
約束字段為自動增長,被約束的字段必須同時被key約束
特點:
第一 只能操作數字
第二 自帶非空屬性
第三 只能對unique字段進行設置
第四 不受刪除影響的
自增約束:
# 1. 創建 tb4 id字段 自增約束, 至少是unique約束, 否則報錯
mysql> create table tb4(id int auto_increment);
ERROR 1075 (42000): Incorrect table definition; there can be only one auto column and it must be defined as a key
# 2. 創建tb4 id字段 自增約束,
mysql> create table tb4(id int unique auto_increment);
Query OK, 0 rows affected (0.30 sec)
# 查看表結構,不難發現id自動默認成了 主鍵約束
mysql> desc tb4;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
+-------+---------+------+-----+---------+----------------+
# 3. 增加數據
mysql> insert into tb4 values(1);
Query OK, 1 row affected (0.12 sec)
# 由於主鍵約束原因 ,重復添加一個值會 報錯
mysql> insert into tb4 values(1);
ERROR 1062 (23000): Duplicate entry '1' for key 'id'
# 4. 不受刪除影響,對於自增的字段,在用delete刪除后,再插入值,該字段仍按照刪除前的位置繼續增長
mysql> select * from tb4;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
# 刪除表中的數據
mysql> delete from tb4;
Query OK, 3 rows affected (0.11 sec)
# 再次查詢
mysql> select * from tb4;
Empty set (0.00 sec)
# 再次增加數據
mysql> insert into tb4 values();
Query OK, 1 row affected (0.11 sec)
# 發現從4 開始
mysql> select * from tb4;
+----+
| id |
+----+
| 4 |
+----+
1 row in set (0.00 sec)
# 原因: delete 不會刪除 id 自增字段的信息,
# show create table tb4;可以看出 AUTO_INCREMENT=5 是保留下一次存數據自增的值
mysql> show create table tb4;
| tb4 | CREATE TABLE `tb4` (
`id` int(11) NOT NULL AUTO_INCREMENT,
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 |
# 5. truncate 清空, 則自增字段的值也被清空
# 清空表
mysql> truncate table tb4;
Query OK, 0 rows affected (0.29 sec)
# 可以看出 沒有自增信息. 表示所有信息被清空了
mysql> show create table tb4;
| tb4 | CREATE TABL
E `tb4` (
`id` int(11) NOT NULL AUTO_INCREMENT,
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
offset偏移量:
#在創建完表后,修改自增字段的起始值
# 1. 創建表student 設置id字段主鍵 自增約束
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);
# 2. 修改 id 字段 自增量
mysql> alter table student auto_increment=4;
Query OK, 0 rows affected (0.12 sec)
Records: 0 Duplicates: 0 Warnings: 0
# 查看表的詳細信息 ,發現 自增了到了4: AUTO_INCREMENT=4
mysql> show create table student;
| student | CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(20) DEFAULT NULL,
`sex` enum('male','female') DEFAULT 'male',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 |
# 3. 增加值 ,的確是從指定偏移量繼續增加
mysql> insert into student(name) values('張三');
Query OK, 1 row affected (0.11 sec)
mysql> select * from student;
+----+--------+------+
| id | name | sex |
+----+--------+------+
| 4 | 張三 | male |
+----+--------+------+
# 4. 創建表的時候可以設置 偏移量
# 也可以創建表時指定auto_increment的初始值,注意初始值的設置為表選項,應該放到括號外
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
)auto_increment=3;
############################################################################################
### 步長:auto_increment_increment,起始偏移量:auto_increment_offset
#設置步長
sqlserver:自增步長
基於表級別
create table t1(
id int。。。
)engine=innodb,auto_increment=2 步長=2 default charset=utf8
mysql自增的步長:
show session variables like 'auto_inc%';
#基於會話級別
set session auth_increment_increment=2 #修改會話級別的步長
#基於全局級別的
set global auth_increment_increment=2 #修改全局級別的步長(所有會話都生效)
#!!!注意了注意了注意了!!!
If the value of auto_increment_offset is greater than that of auto_increment_increment, the value of auto_increment_offset is ignored.
翻譯:如果auto_increment_offset的值大於auto_increment_increment的值,則auto_increment_offset的值會被忽略 ,這相當於第一步步子就邁大了,扯着了蛋
比如:設置auto_increment_offset=3,auto_increment_increment=2
mysql> set global auto_increment_increment=5;
Query OK, 0 rows affected (0.00 sec)
mysql> set global auto_increment_offset=3;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'auto_incre%'; #需要退出重新登錄
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+--------------------------+-------+
create table student(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') default 'male'
);
mysql> insert into student(name) values('egon1'),('egon2'),('egon3');
mysql> select * from student;
+----+-------+------+
| id | name | sex |
+----+-------+------+
| 3 | egon1 | male |
| 8 | egon2 | male |
| 13 | egon3 | male |
+----+-------+------+
foreign key 外鍵約束:
含義:
外鍵的是使兩種原本沒有關系的表產生一定的聯系. 由於在一張表存儲的數據量過大,容易造成數據冗余和效率低下. 把一張表分成兩張表,使用外鍵讓其產生一定的關聯性
特點:
對應外表中的字段至少是unique的,推薦使用主鍵作為關聯字段
外鍵案例:
學生表字段: sid , sname姓名 , gender ,cid外鍵
班級表字段: cid , cname班級名 ,
### 外鍵關聯必須是主鍵,或者至少是唯一unique ###
# 1. 先創建沒有外鍵的表 class
create table class(
cid int primary key auto_increment,
cname char(6));
# 2. 再創建具有外鍵的表 student
create table student(
sid int primary key auto_increment ,
sname char(6) ,
gender enum('男','女') default '男',
cid int ,
# 固定語法,foreign key(當前表主鍵), references 關聯表名(關聯表主鍵)
foreign key(sid) references class(cid)
);
# 3. 查看報表結構
mysql> desc class;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| cid | int(11) | NO | PRI | NULL | auto_increment |
| cname | char(6) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> desc student;
+--------+-------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------+------+-----+---------+----------------+
| sid | int(11) | NO | PRI | NULL | auto_increment |
| sname | char(6) | YES | | NULL | |
| gender | enum('男','女') | YES | | 男 | |
| cid | int(11) | YES | | NULL | |
+--------+-------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
# 4. 添加數據 ,必須先添加沒有外鍵關聯的表,否則有外鍵關聯的表因找不到主鍵而添加失敗
mysql> insert into student(sname,cid) values('李四',1);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`day39`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`sid`) REFERENCES `class` (`cid`))
# 5. 先給class 表插入數據 , 再給student表插入數據(student表中關聯的外鍵一定是存在的,否則報錯)
# class 表添加數據
mysql> insert into class values(1,'高一一班');
Query OK, 1 row affected (0.03 sec)
# 查看 class 表
mysql> select * from class;
+-----+--------------+
| cid | cname |
+-----+--------------+
| 1 | 高一一班 |
+-----+--------------+
1 row in set (0.00 sec)
# student 表添加數據
mysql> insert into student values(1,'趙小','男',1);
Query OK, 1 row affected (0.04 sec)
# 查看student 表
mysql> select * from student;
+-----+--------+--------+------+
| sid | sname | gender | cid |
+-----+--------+--------+------+
| 1 | 趙小 | 男 | 1 |
+-----+--------+--------+------+
1 row in set (0.00 sec)
# 6. 刪除或修改class表都是失敗的,因為student表內還有數據和其關聯,不能修改.
# 只有刪除student表內的所有和其關聯的表才能修改或刪除class表的數據
mysql> delete from class where cid=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`day39`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`sid`) REFERENCES `class` (`cid`))
mysql> update class set cid=2 where cid=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`day39`.`student`, CONSTRAINT `student_ibfk_1` FOREIGN KEY (`sid`) REFERENCES `class` (`cid`))
級聯刪除on delete cascade 和級聯更新 on update cascade:
### 由於外鍵的存在,不能隨意對被關聯表進行修改或刪除.
### 因此產生級聯刪除 和 級聯修改 ,
### 級聯刪除一般不推薦使用,
# 1. 先創建沒有外鍵的表 class1
create table class1(
cid int primary key auto_increment,
cname char(6));
# 2. 再創建具有外鍵的表 student1
create table student1(
sid int primary key auto_increment ,
sname char(6) ,
gender enum('男','女') default '男',
cid int ,
# 固定語法,foreign key(當前表主鍵), references 關聯表名(關聯表主鍵)
foreign key(sid) references class1(cid) on delete cascade on update cascade
);
# 3. 查看表結構和數據
mysql> desc class1;
+-------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+----------------+
| cid | int(11) | NO | PRI | NULL | auto_increment |
| cname | char(6) | YES | | NULL | |
+-------+---------+------+-----+---------+----------------+
2 rows in set (0.01 sec)
mysql> desc student1;
+--------+-------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-------------------+------+-----+---------+----------------+
| sid | int(11) | NO | PRI | NULL | auto_increment |
| sname | char(6) | YES | | NULL | |
| gender | enum('男','女') | YES | | 男 | |
| cid | int(11) | YES | | NULL | |
+--------+-------------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
mysql> select * from class1;
+-----+--------------+
| cid | cname |
+-----+--------------+
| 1 | 高一一班 |
+-----+--------------+
1 row in set (0.00 sec)
mysql> select * from student1;
+-----+--------+--------+------+
| sid | sname | gender | cid |
+-----+--------+--------+------+
| 1 | 趙小 | 男 | 1 |
+-----+--------+--------+------+
1 row in set (0.00 sec)
### 級聯更新 同步更新
## 更新前 兩個表的信息
mysql> select * from class1;
+-----+--------------+
| cid | cname |
+-----+--------------+
| 1 | 高一一班 |
+-----+--------------+
1 row in set (0.00 sec)
mysql> select * from student1;
+-----+--------+--------+------+
| sid | sname | gender | cid |
+-----+--------+--------+------+
| 1 | 趙小 | 男 | 1 |
+-----+--------+--------+------+
1 row in set (0.00 sec)
# 級聯更新
mysql> update class1 set cid=2 where cid=1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1 Changed: 1 Warnings: 0
# 更新后 兩個表的數據同時被更新
mysql> select * from class1;
+-----+--------------+
| cid | cname |
+-----+--------------+
| 2 | 高一一班 |
+-----+--------------+
1 row in set (0.00 sec)
mysql> select * from student1;
+-----+--------+--------+------+
| sid | sname | gender | cid |
+-----+--------+--------+------+
| 2 | 趙小 | 男 | 1 |
+-----+--------+--------+------+
1 row in set (0.00 sec)
### 級聯刪除,同步刪除
## 刪除前兩個表的數據
mysql> select * from class1;
+-----+--------------+
| cid | cname |
+-----+--------------+
| 2 | 高一一班 |
+-----+--------------+
1 row in set (0.00 sec)
mysql> select * from student1;
+-----+--------+--------+------+
| sid | sname | gender | cid |
+-----+--------+--------+------+
| 2 | 趙小 | 男 | 1 |
+-----+--------+--------+------+
1 row in set (0.00 sec)
# 級聯刪除
mysql> delete from class1 ;
Query OK, 1 row affected (0.12 sec)
# 刪除后兩個表的數據
mysql> select * from class1;
Empty set (0.00 sec)
mysql> select * from student1;
Empty set (0.00 sec)