MySQL总论
1. MySQL基本概念
1.1.? 數據庫的概念
數據庫,簡而言之就是存儲數據的倉庫,可以按照一定的數據結構存儲管理大量的數據及數據與數據之間的關系,它本質上是一種信息管理系統。數據庫根據存儲采用的數據結構的不同可以分為許多種,其中常見的有層次式數據庫、網絡式數據庫、關系型數據庫。其中關系型數據庫占據著市場的主流。
1.2.? 關系型數據庫
關系型數據庫是建立在關系模型基礎上的數據庫。這種定義聽起來十分抽象,這里我們不深入討論什么叫做“關系模型”--大學計算機專業專門有一門課叫“離散數學”專門討論過關系模型 --,只是簡單的表述為 利用表來存儲數據,用表和表之間的關系保存數據之間的關系的數據庫稱為關系型數據庫,這個定義不太嚴謹,但是更好理解。
1.3.? 常見的關系型數據庫
商業數據庫:
Oracle -- 甲骨文公司開發,市場占有率第一
SQLServer -- 微軟公司開發,.Net技術中常用
DB2 -- IBM公司開發
Sybase -- Sybase公司開發
開源數據庫:
MySql -- 瑞典MySql AB研發,非常受歡迎,已經被Oracle收購
SQLite -- 小型輕量級開源關系型數據庫,常用作嵌入式設備數據庫
1.4.? MySql數據庫的安裝配置
1.4.1.MySQL安裝配置
安裝配置步驟見附加文檔
1.4.2.MySQL安裝目錄
MySQL的數據存儲目錄為data,data目錄通常在\MySQLServer5.1\data位置。在data下的每個目錄都代表一個數據庫。
MySQL的安裝目錄下:
??? bin目錄中都是可執行文件;
??? my.ini文件是MySQL的配置文件;
1.5.? 基本命令
1.5.1.啟動和關閉mysql服務器
啟動:net start mysql;
關閉:net stop mysql;
在啟動mysql服務后,打開windows任務管理器,會有一個名為mysqld.exe的進程運行,所以mysqld.exe才是MySQL服務器程序。
1.5.2.客戶端登錄退出mysql
在啟動MySQL服務器后,我們需要使用管理員用戶登錄MySQL服務器,然后來對服務器進行操作。登錄MySQL需要使用MySQL的客戶端程序:mysql.exe
登錄:mysql -u root -p 123 -h localhost;
-u:后面的root是用戶名,這里使用的是超級管理員root;
-p:后面的123是密碼,這是在安裝MySQL時就已經指定的密碼;
-h:后面給出的localhost是服務器主機名,它是可以省略的,例如:mysql -u root -p 123;
退出:quit或exit;
在登錄成功后,打開windows任務管理器,會有一個名為mysql.exe的進程運行,所以mysql.exe是客戶端程序。
2. MySql常見概念
2.1.? 數據庫服務器
指的就是一個數據庫管理程序,這個程序可以管理多個數據庫。
2.2.? 數據庫
一個數據庫服務器可以管理多個數據庫,可以認為是一個數據的“倉庫”,一般一個web應用對應一個數據庫。
2.3.? 表
在保存應用實體數據時,通常會在數據庫中創建多個表,以保存應用程序實體數據。一般來說應用程序中的一個javabean類可以對應一張數據庫表。
2.4.? 表記錄
表中以一行記錄保存一條信息,這樣的一條記錄稱為表記錄。可以認為一個javabean對象對應一條表記錄。
3. SQL語言
3.1.? 基本概念
3.1.1.SQL
SQL--Structured Query Language, 結構化查詢語言,是關系型數據庫通用的操作語言。
是一種非過程性語言。
由美國國家標準局(ANSI)與國際標準化組織(ISO)制定SQL標準。各大數據庫廠商都對其做了實現。所以我們只要學會了SQL語言,就可以操作各大關系型數據庫了。
為加強SQL的語言能力,各廠商增強了過程性語言的特征,增加了一些非標準的SQL,這樣的SQL稱為該數據庫的“方言”。
SQL是用來存取關系數據庫的語言,具有查詢、操縱、定義和控制關系型數據庫的四方面功能
3.2.? 操作數據庫
3.2.1.創建數據庫
語法:
CREATE? DATABASE? [IF NOT EXISTS]? db_name? [create_specification [, create_specification] ...]
create_specification:
[DEFAULT] CHARACTER SET charset_name? |? [DEFAULT] COLLATE collation_name
其中charset_name是為數據庫指定的默認字符集
Collate是為數據庫指定的默認校對規則
校對規則是在字符集內用于比較字符的一套規則,可以控制select查詢時where條件大小寫是否敏感的規則。
練習:
~創建一個名稱為mydb1的數據庫。
??? CREATE DATABASE mydb1;
~創建一個使用gbk字符集的mydb2數據庫。
??? CREATE DATABASE mydb2 CHARACTER SET gbk;
~創建一個使用utf8字符集,并帶校對規則的mydb3數據庫。
??? CREATE DATABASE mydb3 CHARACTER SET utf8 COLLATE utf8_bin;
3.2.2.查看數據庫
語法:
顯示所有數據庫:
SHOW DATABASES
顯示數據庫創建語句:
?SHOW CREATE DATABASE db_name
練習:
~查看當前數據庫服務器中的所有數據庫
?? SHOW DATABASES;
~查看前面創建的mydb2數據庫的定義信息
?? SHOW CREATE DATABASE mydb2;
3.2.3.修改數據庫
語法:
ALTER DATABASE db_name??[alter_specification [, alter_specification] ...]
alter_specification:???
[DEFAULT] CHARACTER SET charset_name? | [DEFAULT] COLLATE collation_name
練習:
~查看服務器中的數據庫,并把mydb2庫的字符集修改為utf8
?? ALTER DATABASE mydb2 CHARACTER SET utf8;
3.2.4.刪除數據庫
語法:
DROP DATABASE? [IF EXISTS]? db_name
練習:
~刪除前面創建的mydb1數據庫
?? DROP DATABASE mydb1;
3.2.5.選擇數據庫
語法:
選擇數據庫:use db_name;
查詢當前選擇的數據: select database();
沒有退出數據庫的命令,如果想退出當前數據庫進入另一個數據,直接use 另一個數據庫 就可以了
3.3.? 操作表
3.3.1.SQL中常見數據類型
1)字符串型
VARCHAR:
變長的字符串,需要在聲明字段時指定能存儲的最大字符數,真實占用的空間取決于存入的字符數,存入的越多占用空間越多。適合保存內容長度不定的字符類型數據。能包含數據的大小,mysql5.0以前0~255字節,mysql5.0以后0~65535字節
CHAR:
定長字符串,需要在聲明字段時指定固定字符數。即使存入的字符數少于該長度,該字段也會占用該固定長度。適合存儲長度不變的字符類型數據。能包含數據的大小,0~255字節
2)大數據類型
BLOB:
大二進制類型,可以存入二進制類型的數據,通過這個字段,可以將圖片、音頻、視頻等數據以二進制的形式存入數據庫。最大為4GB。
TEXT:
大文本,被聲明為這種類型的字段,可以保存大量的字符數據,最大為4GB。
注意:text屬于mysql的方言,在其他數據庫中為clob類型
3)數值型
TINYINT:占用1個字節,相對于java中的byte
SMALLINT:占用2個字節,相對于java中的short
INT:占用4個字節,相對于java中的int
BIGINT:占用8個字節,相對于java中的long
FLOAT:4字節單精度浮點類型,相對于java中的float
DOUBLE:8字節雙精度浮點類型,相對于java中的double
4)邏輯型
BIT:
位類型,可以存儲指定位的值,可以指定位的個數,如果不指定則默認值為1位,即只能保存0或1,對應到java中可以是boolean型。
5)日期型
DATE:日期
TIME:時間
DATETIME:日期時間
TIMESTAMP:時間戳
**DATETIME和TIMESTAMP的區別?
* DATETIME和TIMESTAMP顯示的結果是一樣的,都是固定的"YYYY-MM-DD HH:MM:SS"的格式
* DATETIME支持的范圍是'1000-01-01 00:00:00'到'9999-12-31 23:59:59'。TIMESTAMP的顯示范圍是'1970-01-01 00:00:00'到2037年,且其實際的存儲值為1970年到當前時間的毫秒數。
* 在建表時,列為TIMESTAMP的日期類型可以設置一個默認值,而DATETIME不行。
* 在更新表時,可以設置TIMESTAMP類型的列自動更新時間為當前時間。
3.3.2.字段約束
字段的約束:約束了表中一個字段的值需要符合的條件
1)定義主鍵約束
通常每張表都會有一個字段或多個字段聯合起來唯一標識表記錄,這樣的字段稱為這張表的主鍵。我們可以為這樣的字段增加主鍵約束。主鍵約束要求字段必須不能為空且值必須唯一。
增加主鍵約束:PRIMARY KEY
可以在定義主鍵時指定主鍵的自動增長auto_increment,這樣主鍵就不需要人為的維護,在新增記錄時不需要指定主鍵的值,數據庫會自動維護一個計數器,每次計數器的值+1后作為主鍵,保證主鍵的唯一性。
2)定義唯一約束
如果需要指定某個字段的值不能重復,可以為該字段指定唯一約束
增加唯一約束:unique
3)定義非空約束
如果需要指定某個字段的值不能為空,可以為該字段指定非空約束
增加非空約束:not null
4)外鍵約束
??? 見3.6
3.3.3.新增表
語法:
CREATE TABLE table_name
(
field1? datatype,
field2? datatype,
field3? datatype
)[character set 字符集] [collate 校對規則]
field:指定列名 datatype:指定列類型
?
注意:創建表時,要根據需保存的數據創建相應的列,并根據數據的類型定義相應的列類型。
創建表時,一般不需要指定字符集編碼和校對規則,和數據庫保持一致即可。
?
練習
~創建employee表
| 字段 | 屬性 |
| id | 整型 |
| name | 字符型 |
| gender | 字符型 |
| birthday | 日期型 |
| entry_date | 日期型 |
| job | 字符型 |
| salary | 小數型 |
| resume | 大文本型 |
?
?
?
?
?
?
?
?
?
?
?
?
create table employee(id int primary key auto_increment,name varchar(20) unique,gender bit not null,birthday date,entry_date date,job varchar(100),salary double,resume text);3.3.4.查看表
語法:
查看表結構:
desc tabName
查看當前所有表:
show tables
查看當前數據庫表建表語句
show create table tabName;
3.3.5.修改表
語法:
增加列:
ALTER TABLE tabname ADD (column datatype [DEFAULT expr][, column datatype]...);
?
修改列:
ALTER TABLE tabname MODIFY (column datatype [DEFAULT expr][, column datatype]...);
?
刪除列:
ALTER TABLE tabname DROP (column);
?
修改表名:
ALTER TABLE old_tabname RENAME TO new_tabname;
或
RENAME TABLE old_tabname TO new_tabname;
?
修改列名稱:
ALTER TABLE tabname CHANGE [column] old_col_name new_col_name datatype
?
修改列的順序:
ALTER TABLE tabname MODIFY col_name1 datatype AFTER col_name2;
?
修改表的字符集:
ALTER TABLE tabname CHARACTER SET character_name;
練習:
~在上面員工表的基礎上增加一個image列。
alter table employee add image blob;
~修改job列,使其長度為60。
alter table employee modify job varchar(60);
~刪除gender列。
alter table employee drop gender;
~表名改為user。
alter table employee rename to user;
??? 或
rename table employee to user;
~列名name修改為username
alter table user change name username varchar(20);
~將image插入到gender列的后面
alter table user modify image blob after gender;
~修改表的字符集為utf8
alter table user character set utf8;
3.3.6.刪除表
語法:
DROP TABLE tabname;
練習:
~刪除user表
drop table user;
3.4.? 操作表記錄
3.4.1.INSERT
語法:
INSERT INTO tabname [(column [, column...])] VALUES (value [, value...]);
注意:
插入的數據應與字段的數據類型相同
數據的大小應在列的規定范圍內
在values中列出的數據位置必須與被加入的列的排列位置相對應
字符串和日期格式的數據要用單引號引起來
如果要插入所有字段可以省寫列列表,直接按表中字段順序寫值列表
?
練習:
~向員工表中插入三條數據
insert into employee (id,name,gender,birthday,entry_date,job,salary,resume)values(null,'張飛',1,'1990-09-09','2000-01-01','打手',998.0,'真的很能打...');insert into employeevalues(null,'關羽',0,'1990-08-08','1990-08-09','財神',9999999.0,'公司掙錢就指著他了...');insert into employeevalues(null,'劉備',1,'1990-06-06','1990-09-09','ceo',10.0,'公司的 ceo,基本沒啥事干..'),(null,'趙云',1,'2010-06-01','2010-06-01','保鏢',400.0,'老板的 貼身護衛...');3.4.2.mysql亂碼解決:
查看當前數據庫中字符集配置:
show variables like'character%';
其中:
client是客戶端使用的字符集。
connection是連接數據庫的字符集設置類型,如果程序沒有指明連接數據庫使用的字符集類型就按照服務器端默認的字符集設置。
database是數據庫服務器中某個庫使用的字符集設定,如果建庫時沒有指明,將使用服務器安裝時指定的字符集設置。???
results是數據庫給客戶端返回時使用的字符集設定,如果沒有指明,使用服務器默認的字符集。??????
server是服務器安裝時指定的默認字符集設定。??????
system是數據庫系統使用的字符集設定。(utf-8不可修改)
?
set names xxx; 命令是客戶端通知服務器和當前客戶端交互時使用什么編碼,但是這種方式每次新開客戶端都需要通知服務器 很麻煩???
我們可以修改mysql/my.ini,將default-character-set=gbk,這是修改服務器默認認為的客戶端的字符集編碼
這樣一來,大部分人都是gbk的客戶端,不需要設置任何東西,連進來就沒亂碼.如果有個別的人客戶端不是gbk,也可以通過set names xxx;的方式聲明自己的編碼集,也沒有亂碼.
?
3.4.3.UPDATE
語法:
UPDATE tab_name SET col_name1=expr1 [, col_name2=expr2 ...]??[WHERE where_definition]???
UPDATE語法可以用新值更新原有表行中的各列。
SET子句指示要修改哪些列和要給予哪些值。
WHERE子句指定應更新哪些行。如沒有WHERE子句,則更新所有的行。
練習:
~將所有員工薪水修改為5000元。
update employee set salary=5000;
~將姓名為’張飛’的員工薪水修改為3000元。
update employee set salary=3000 where name='張飛';
~將姓名為’關羽’的員工薪水修改為4000元,job改為”耍大刀”。
update employee set salary=4000,job='耍大刀' where name='關羽';???
~將劉備的薪水在原有基礎上增加1000元。
update employee set salary=salary+1000 where name='劉備';
?
3.4.4.DELETE
語法:
delete from tab_name?[WHERE where_definition]
where用來篩選要刪除的記錄,如果不使用where子句,將刪除表中所有數據。
delete語句不能刪除某一列的值(可使用update)
delete語句僅刪除記錄,不刪除表本身。如要刪除表,使用drop table語句。
TRUNCATE TABLE tab_name語句也可以刪除表中數據,它和delete有所不同。delete是一條條刪除記錄,truncate是摧毀整表再重建相同結構的表,truncate效率更高。
?
練習:
~刪除表中名稱為’張飛’的記錄。
delete from employee where name='張飛';
~刪除表中所有記錄。
delete from employee;
~使用truncate刪除表中記錄。
truncate table employee;
?
3.4.5.SELECT
(1)基本的查詢
語法:
SELECT [DISTINCT] *|{column1, column2. column3..} FROM table;
select 指定查詢哪些列的數據。
column指定列名。
*號代表查詢所有列。
from指定查詢哪張表。
DISTINCT可選,指顯示結果時,是否剔除重復數據
練習:
create table exam(id int primary key auto_increment,name varchar(20) not null,chinese double,math double,english double);insert into exam values(null,'關羽',85,76,70);insert into exam values(null,'張飛',70,75,70);insert into exam values(null,'趙云',90,65,95);insert into exam values(null,'張三豐',82,79,null);~查詢表中所有學生的信息。
select * from exam;
~查詢表中所有學生的姓名和對應的英語成績。
select name,english from exam;
~過濾表中重復數據。
select distinct english from exam;
~在所有學生分數上加10分特長分顯示。
select name,english+10 ,chinese+10 ,math+10 from exam;
~統計每個學生的總分。
select name,english+math+chinese from exam;
~使用別名表示學生總分。
select name as 姓名,english+math+chinese as 總分 from exam;
select name 姓名,english+math+chinese 總分 from exam;
select name english from exam;//~!這是錯的
?
(2)使用where子句的查詢
語法:
Select *|列名 from tablename [WHERE where_definition]
其中Where子句中支持:?
Like語句中,% 代表零個或多個任意字符,_ 代表一個字符,例first_name like ‘_a%’;
?
練習:
~查詢姓名為關羽的學生成績
select * from exam where name='關羽';
~查詢英語成績大于90分的同學
select * from exam where english > 90;
~查詢總分大于230分的所有同學
select name 姓名,english+math+chinese 總分 from exam where english+math+chinese>230;
~查詢語文分數在 80-100之間的同學。
???????? ???????? select name,chinese from exam where chinese between 80 and 100;
~查詢數學分數為75,76,77的同學。再查詢分數不在這個范圍內的同學
??? select name,math from exam where math in (75,76,77);
??? select name,math from exam where math not in (75,76,77);
~查詢所有姓張的學生成績。
select * from exam where name like '張%';
select * from exam where name like '張_';
select * from exam where name like '張__';
~查詢數學分>70,語文分>80的同學。
select * from exam where math>70 and chinese>80;
?
(3)排序查詢
語法:
SELECT column1, column2. column3.. FROM table order by column asc|desc;
Order by 指定排序的列,排序的列即可是表中的列名,也可以是select 語句后指定的列名。
Asc 升序、Desc 降序
ORDER BY 子句應位于SELECT語句的結尾。
?
練習:
~對英語成績排序后輸出。
select name ,english from exam order by english desc;
~對總分排序按從高到低的順序輸出
??? select name 姓名, ifnull(english,0)+ifnull(math,0)+ifnull(chinese,0) 總分 from exam order by 總分 desc;
~對姓張的學生成績排序輸出
select name 姓名, ifnull(english,0)+ifnull(math,0)+ifnull(chinese,0) 總分 from exam where name like '張%' order by 總分 desc;
?
(4)聚合函數
SQL提供的聚合函數有計數函數COUNT()、求和函數SUM()、平均值函數AVG()、最大值函數MAX()、最小值函數MIN()等。如下表:
| 函數名稱 | 函數功能 |
| COUNT() | 返回選取結果集中行的數目 |
| SUM() | 返回選取結果集中所有值的總和 |
| AVG() | 返回選取結果集中所有值的平均值 |
| MAX() | 返回選取結果集中所有值的最大值 |
| MIN() | 返回選取結果集中所有值的最小值 |
?
?
?
?
?
?
?
?
?
語法:
求符合條件的記錄中指定列的記錄數
??? select count(列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的和值
??? Select sum(列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的平均值
??? Select avg (列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的最大值
??? Select max(列名)… from tablename [WHERE where_definition]
求符合條件的記錄中指定列的最小值
??? Select min(列名)… from tablename [WHERE where_definition]
練習:
~統計一個班級共有多少學生?
select count(*) from exam;
~統計數學成績大于75的學生有多少個?
select count(*) from exam where math>75;
~統計總分大于230的人數有多少?
select count(name) from exam
where ifnull(english,0)+ifnull(math,0)+ifnull(chinese,0) >230;
~統計一個班級數學總成績?
select sum(math) from exam;
~統計一個班級語文、英語、數學各科的總成績
select sum(math) ,sum(english),sum(chinese) from exam;
~統計一個班級語文、英語、數學的成績總和
select sum(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) from exam;
~統計一個班級語文成績平均分
select sum(chinese)/count(*) from exam;
~求一個班級數學平均分?
select avg(math) from exam;
~求一個班級總分平均分?
select avg(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) ?? ???????? from exam;
~求班級最高分和最低分
select max(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) ???????? from exam;
select min(ifnull(math,0)+ifnull(english,0)+ifnull(chinese,0)) ? ???????? from exam;
(5)分組查詢
語法:
SELECT column1, column2. column3.. FROM???? table group by column having ...
?
練習:
create table orders(id int,product varchar(20),price float);insert into orders(id,product,price) values(1,'電視',900);insert into orders(id,product,price) values(2,'洗衣機',100);insert into orders(id,product,price) values(3,'洗衣粉',90);insert into orders(id,product,price) values(4,'桔子',9);insert into orders(id,product,price) values(5,'洗衣粉',90);?
~對訂單表中商品歸類后,顯示每一類商品的總價
select product ,sum(price) from orders group by product;
~查詢購買了幾類商品,并且每類總價大于100的商品
select product ,sum(price)
??? from orders group by product having sum(price) >100;
~查詢單價小于100而總價大于100的商品的名稱.
??? select product
??? from orders
??? where price < 100 group by product having sum(price)>100;
?
**where子句和having子句都可以進行過濾器,但是使用場景有所不同:
* where子句對分組之前的數據進行過濾,不能使用聚合函數
* having子句對分組之后的數據進行過濾,可以使用聚合函數
* 使用where子句的地方都可以用having替代,但是使用having的地方一般不能用 where替代
3.5.? mysql數據庫的備份與恢復
3.5.1.備份數據庫:
cmd窗口中使用mysqldump 備份數據庫
mysqldump -u root -p db_name > c:/xxx.sql
例如:mysqldump -u root -p mydb2 > c:/mydb2.sql
3.5.2.恢復數據庫:
方式1:cmd窗口中使用mysql命令 恢復數據庫,注意,只能恢復數據庫中的數據,不能恢復數據庫本身!所以要提前建好數據庫.
mysql -u root -p db_name < c:/xxx.sql
例如:mysql -u root -p mydb2 < c:/mydb2.sql
?
方式2:在mysql命令下,source xxx.sql,這個命令的作用就是,在當前位置執行sql文件中的所有的sql.首先新建出數據庫,進入數據庫,在source執行備份的sql文件即可。
例如:source c:/xxx.sql
注意:如果在cmd窗口下,執行出現“拒絕訪問”提示,用管理員打開cmd窗口即可。
3.6.? 外鍵約束
3.6.1.外鍵概念
數據庫用表來保存數據,但是現實中,數據和數據之間往往具有一定的關系,在設計表時應該如何來保存這種關系呢?我們來看如下圖。
?
一個部門可以具有多個員工,而一個員工只能屬于一個部門。對于這種類型的關系我們稱之為1對多的關系。
那么我們該如何保存他們之間的關系呢?
可不可以在dept表中設計一張表記錄部門中員工的信息呢?
?
我們發現這是不可行的,因為一個部門中可能有多個員工,這就導致emp_id中一個字段可能需要保存多個值,這是不可行的。
那么反過來,可否在emp表保存員工所屬部門id呢?
這種方式是可行的,因為一個員工只能屬于一個部門,dept_id中只需存儲一個值即可。
雖然我們設計了這樣的字段保存兩表之間的關系,但是數據庫并不知道這樣的關系。我們可以設想,如下的情況。
“公司老總發現科技部不掙錢,決定解散科技部”,對應到數據庫時,就是如下的sql
delete from dept where id = 004;
正確的執行后,數據庫中的數據變為如下
?
我們發現“555 郭德綱”人還在,所屬部門卻沒有了,數據之間的對應關系出現了問題,我們稱為違反了數據庫的“完整性”。
之所以產生這樣的問題,是因為雖然我們知道dept_id要參考dept表的id列,但是數據庫并不知道,所以在刪除數據造成違反“不完整”性的情況下數據庫沒有任何提示。
為了防止這樣的問題產生,可以通過外鍵明確的通知數據庫維系這種關系。
一旦任何操作違反了這種關系,數據庫會阻止并報錯。
?
3.6.2.建表時增加外鍵:
foreign key(ordersid) references orders(id)
3.6.3.修改方式增加外鍵:
alter table book add [constraint FK_BOOK] foreign key(pubid) references pub_com(id) [on delete restrict] [on update restrict];
?
可以明確指定外鍵的名稱,如果不指定外鍵的名稱,mysql會自動為你創建一個外鍵名稱。
RESTRICT : 只要本表格里面有指向主表的數據, 在主表里面就無法刪除相關記錄。
CASCADE : 如果在foreign key 所指向的那個表里面刪除一條記錄,那么在此表里面的跟那個key一樣的所有記錄都會一同刪掉。
??? ??? ??? ???
3.6.4.刪除外鍵
alter table 表名 drop foreign key 外鍵名
3.6.5.實驗外鍵
略
4. 多表設計
4.1.? 多表設計概念
在講解外鍵時,我們提到了表和表之間往往存在著一定的關系,那么除了上述的1對多關系外還有哪些種關系呢?又如何設計外鍵來保存這些不同的關系呢?下面,我們一起來討論表和表中的三種關系。
4.2.? 三種關系及外鍵設計
一對一表和表之間的關系分為三種,分別是1對1、1對多、多對多,下面就用具體的例子講解這三種關系
4.2.1.?
班級表和教室表之間的關系,一個班級只能在一個教室上課,一個教室也只能放下一個班級,這種關系就稱為一對一的關系,對于一對一的關系,可以在任意一方保存另一方的主鍵作為外鍵保存兩表之間的關系。
?
?
4.2.2.一對多
學生表和班級表的關系,一個班級可以有多個學生而一個學生只能屬于一個班級,這種關系稱為一對多的關系,對于一對多的關系,可以在多的一方設計外鍵保存一的一方的主鍵作為外鍵保存兩表之間的關系。
?
4.2.3.多對多:
學生表和教師表的關系,一個學生可以由多個老師教授,一個老師也可以教授多個學生,這種關系稱為多對多的關系,對于多對多的關系,需要設計一張第三方關系表保存兩張表主鍵之間的對應關系。
?
5.????? 多表查詢
5.1.? 多表查詢概念
表和表之間往往是存在關系的,而有時我們需要的數據在多張表中,如何跨著多張表查詢數據呢?這就涉及到多表查詢了
準備數據:
create table dept(id int primary key auto_increment,name varchar(20));insert into dept values(null,'財務部'),(null,'人事部'),(null,'科技部'),(null,'銷售部'); create table emp(id int primary key auto_increment,name varchar(20),dept_id int);insert into emp values(null,'張飛',1),(null,'關羽',2),(null,'劉備',3),(null,'趙云',5);需求:查詢所有部門名稱和對應的員工名稱。5.2.? 多表查詢設計
5.2.1.笛卡爾積查詢:
這是一種最原始的查詢方式,其實就是兩張表相乘的結果,如果左表有m條記錄,右表有n條記錄,則查詢出來m*n條記錄.雖然查出數據了,但是其中包含了大量錯誤的數據,所以這種查詢我們通常不使用。
select * from dept,emp;
?
?
5.2.2.內連接查詢
內連接查詢:只查詢左邊表有且右邊表也有的數據,本質上是依據外鍵關系,在笛卡爾積查詢的基礎上過濾出正確的數據。通過觀察結果,我們發現結果中只有兩邊都有對應數據的數據才能被查出來。
select * from dept ,emp where dept.id = emp.dept_id;
select * from dept inner join emp on dept.id = emp.dept_id;
?
5.2.3.外連接查詢:
內連接查詢只能查找出兩邊表都有對應數據的數據,如果兩邊冗余的數據也需要查詢時該怎么辦呢?
(1)左外連接查詢:在內連接的基礎上增加上左邊表有而有邊表沒有的記錄
select * from dept left join emp on dept.id = emp.dept_id;
?
#其中,left join 也可以寫成 left outer join;
(2)右外連接查詢:在內連接的基礎上增加上右邊表有而左邊表沒有的記錄
select * from dept right join emp on dept.id = emp.dept_id;
?
#其中,right join 也可以寫成 right outer join;
(3)全外連接查詢:在內連接的基礎上增加左邊表有而右邊表沒有的記錄和右邊表有而左邊表沒有的記錄
#mysql 不支持全外連接,但是其他的數據庫支持,比如SQL Server
select * from dept full join emp on dept.id = emp.dept_id;
?
#我們可以在mysql中使用union關鍵字模擬全外連接
select * from dept left join emp on dept.id = emp.dept_id
union
select * from dept right join emp on dept.id = emp.dept_id;
?
#其中,full join 也可以寫成 full outer join;
?
?
?
轉載于:https://www.cnblogs.com/chuijingjing/p/10307320.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
- 上一篇: 端口映射与主机映射
- 下一篇: dbcp_c3p0连接mysql8.0.