mysq表的三種關係,資料的增刪改以及單表多表查詢
阿新 • • 發佈:2018-11-11
一丶三種關係
分析步驟: #1、先站在左表的角度去找 是否左表的多條記錄可以對應右表的一條記錄,如果是,則證明左表的一個欄位foreign key 右表一個欄位(通常是id) #2、再站在右表的角度去找 是否右表的多條記錄可以對應左表的一條記錄,如果是,則證明右表的一個欄位foreign key 左表一個欄位(通常是id) #3、總結: #多對一: 如果只有步驟1成立,則是左表多對一右表 如果只有步驟2成立,則是右表多對一左表 #多對多 如果步驟1和2同時成立,則證明這兩張表時一個雙向的多對一,即多對多,需要定義一個這兩張表的關係表來專門存放二者的關係 #一對一: 如果1和2都不成立,而是左表的一條記錄唯一對應右表的一條記錄,反之亦然。這種情況很簡單,就是在左表foreign key右表的基礎上,將左表的外來鍵欄位設定成unique即可如何找出兩張表之間的關係
1.表的三種關係
(1)書和出版社
一對多(或多對一):一個出版社可以出版很多本書.
關聯方式:foreign key
create table press( id int primary key auto_increment, name varchar(20) ); create table book( id int primary key auto_increment, name varchar(20), press_id書和出版社int not null, constraint fk_book_press foreign key(press_id) references press(id) on delete cascade on update cascade ); # 先往被關聯表中插入記錄 insert into press(name) values ('北京工業地雷出版社'), ('人民音樂不好聽出版社'), ('智慧財產權沒有用出版社') ; # 再往關聯表中插入記錄 insert into book(name,press_id) values ('九陽神功',1), ('九陰真經',2), ('九陰白骨爪',2), ('獨孤九劍',3), ('降龍十巴掌',2), ('葵花寶典',3) ; 查詢結果: mysql> select * from book; +----+-----------------+----------+ | id | name | press_id | +----+-----------------+----------+ | 1 | 九陽神功 | 1 | | 2 | 九陰真經 | 2 | | 3 | 九陰白骨爪 | 2 | | 4 | 獨孤九劍 | 3 | | 5 | 降龍十巴掌 | 2 | | 6 | 葵花寶典 | 3 | +----+-----------------+----------+ 6 rows in set (0.00 sec) mysql> select * from press; +----+--------------------------------+ | id | name | +----+--------------------------------+ | 1 | 北京工業地雷出版社 | | 2 | 人民音樂不好聽出版社 | | 3 | 智慧財產權沒有用出版社 | +----+--------------------------------+ 3 rows in set (0.00 sec)
(2)作者和書籍的關係
多對多:一個作者可以寫多本書,一本書也可以有很多個作者,雙向的一對多,即多對多
關聯方式:foreign key + 一張新的表
# 建立被關聯表author表,之前的book表在講多對一的關係已建立 create table author( id int primary key auto_increment, name varchar(20) ); #這張表就存放了author表和book表的關係,即查詢二者的關係查這表就可以了 create table author2book( id int not null unique auto_increment, author_id int not null, book_id int not null, constraint fk_author 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(author_id,book_id) ); #插入四個作者,id依次排開 insert into author(name) values('egon'),('alex'),('wusir'),('yuanhao'); # 每個作者的代表作 egon: 九陽神功、九陰真經、九陰白骨爪、獨孤九劍、降龍十巴掌、葵花寶典 alex: 九陽神功、葵花寶典 wusir:獨孤九劍、降龍十巴掌、葵花寶典 yuanhao:九陽神功 # 在author2book表中插入相應的資料 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) ; # 現在就可以查author2book對應的作者和書的關係了 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 | +----+-----------+---------+ 12 rows in set (0.00 sec)作者和書籍的關係
(3)使用者和部落格
一對一:一個使用者只能註冊一個部落格,即一對一的關係.
關聯方式:foreign key + unique
#例如: 一個使用者只能註冊一個部落格 #兩張表: 使用者表 (user)和 部落格表(blog) # 建立使用者表 create table user( id int primary key auto_increment, name varchar(20) ); # 建立部落格表 create table blog( id int primary key auto_increment, url varchar(100), user_id int unique, constraint fk_user foreign key(user_id) references user(id) on delete cascade on update cascade ); #插入使用者表中的記錄 insert into user(name) values ('alex'), ('wusir'), ('egon'), ('xiaoma') ; # 插入部落格表的記錄 insert into blog(url,user_id) values ('http://www.cnblog/alex',1), ('http://www.cnblog/wusir',2), ('http://www.cnblog/egon',3), ('http://www.cnblog/xiaoma',4) ; # 查詢wusir的部落格地址 select url from blog where user_id=2; 使用者和部落格(一對一)使用者和部落格的關係
二丶資料的增刪改
一、 在MySQL管理軟體中,可以通過SQL語句中的DML語言來實現資料的操作,包括 1.使用INSERT實現資料的插入 2.UPDATE實現資料的更新 3.使用DELETE實現資料的刪除 4.使用SELECT查詢資料以及。 二、插入資料 INSERT 1. 插入完整資料(順序插入) 語法一: INSERT INTO 表名(欄位1,欄位2,欄位3…欄位n) VALUES(值1,值2,值3…值n); 語法二: INSERT INTO 表名 VALUES (值1,值2,值3…值n); 2. 指定欄位插入資料 語法: INSERT INTO 表名(欄位1,欄位2,欄位3…) VALUES (值1,值2,值3…); 3. 插入多條記錄 語法: INSERT INTO 表名 VALUES (值1,值2,值3…值n), (值1,值2,值3…值n), (值1,值2,值3…值n); 4. 插入查詢結果 語法: INSERT INTO 表名(欄位1,欄位2,欄位3…欄位n) SELECT (欄位1,欄位2,欄位3…欄位n) FROM 表2 WHERE …; 三、更新資料UPDATE 語法: UPDATE 表名 SET 欄位1=值1, 欄位2=值2, WHERE CONDITION; 示例: UPDATE mysql.user SET password=password(‘123’) where user=’root’ and host=’localhost’; 四、刪除資料DELETE 語法: DELETE FROM 表名 WHERE CONITION; 示例: DELETE FROM mysql.user WHERE password=’’;
三丶 單表查詢
一、單表查詢的語法 SELECT 欄位1,欄位2... FROM 表名 WHERE 條件 GROUP BY field HAVING 篩選 ORDER BY field LIMIT 限制條數 二、關鍵字的執行優先順序(重點) 重點中的重點:關鍵字的執行優先順序 from where group by having select distinct order by limit 1.找到表:from 2.拿著where指定的約束條件,去檔案/表中取出一條條記錄 3.將取出的一條條記錄進行分組group by,如果沒有group by,則整體作為一組 4.將分組的結果進行having過濾 5.執行select 6.去重 7.將結果按條件排序:order by 8.限制結果的顯示條數
#建立表,設定欄位的約束條件 create table employee( id int primary key auto_increment, name varchar(20) not null, sex enum('male','female') not null default 'male', #大部分是男的 age int(3) unsigned not null default 28, hire_date date not null, post varchar(50), post_comment varchar(100), salary double(15,2), office int,#一個部門一個屋 depart_id int ); # 查看錶結構 mysql> desc employee; +--------------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +--------------+-----------------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | emp_name | varchar(20) | NO | | NULL | | | sex | enum('male','female') | NO | | male | | | age | int(3) unsigned | NO | | 28 | | | hire_date | date | NO | | NULL | | | post | varchar(50) | YES | | NULL | | | post_comment | varchar(100) | YES | | NULL | | | salart | double(15,2) | YES | | NULL | | | office | int(11) | YES | | NULL | | | depart_id | int(11) | YES | | NULL | | +--------------+-----------------------+------+-----+---------+----------------+ 10 rows in set (0.08 sec) #插入記錄 #三個部門:教學,銷售,運營 insert into employee(name ,sex,age,hire_date,post,salary,office,depart_id) values ('egon','male',18,'20170301','老男孩駐沙河辦事處外交大使',7300.33,401,1), #以下是教學部 ('alex','male',78,'20150302','teacher',1000000.31,401,1), ('wupeiqi','male',81,'20130305','teacher',8300,401,1), ('yuanhao','male',73,'20140701','teacher',3500,401,1), ('liwenzhou','male',28,'20121101','teacher',2100,401,1), ('jingliyang','female',18,'20110211','teacher',9000,401,1), ('jinxin','male',18,'19000301','teacher',30000,401,1), ('xiaomage','male',48,'20101111','teacher',10000,401,1), ('歪歪','female',48,'20150311','sale',3000.13,402,2),#以下是銷售部門 ('丫丫','female',38,'20101101','sale',2000.35,402,2), ('丁丁','female',18,'20110312','sale',1000.37,402,2), ('星星','female',18,'20160513','sale',3000.29,402,2), ('格格','female',28,'20170127','sale',4000.33,402,2), ('張野','male',28,'20160311','operation',10000.13,403,3), #以下是運營部門 ('程咬金','male',18,'19970312','operation',20000,403,3), ('程咬銀','female',18,'20130311','operation',19000,403,3), ('程咬銅','male',18,'20150411','operation',18000,403,3), ('程咬鐵','建立員工表,並插入資料
1.where約束
where子句中可以使用 1.比較運算子:>、<、>=、<=、<>、!= 2.between 80 and 100 :值在80到100之間 3.in(80,90,100)值是10或20或30 4.like 'xiaomagepattern': pattern可以是%或者_。%小時任意多字元,_表示一個字元 5.邏輯運算子:在多個條件直接可以使用邏輯運算子 and or not
#1 :單條件查詢 mysql> select id,emp_name from employee where id > 5; +----+------------+ | id | emp_name | +----+------------+ | 6 | jingliyang | | 7 | jinxin | | 8 | xiaomage | | 9 | 歪歪 | | 10 | 丫丫 | | 11 | 丁丁 | | 12 | 星星 | | 13 | 格格 | | 14 | 張野 | | 15 | 程咬金 | | 16 | 程咬銀 | | 17 | 程咬銅 | | 18 | 程咬鐵 | #2 多條件查詢 mysql> select emp_name from employee where post='teacher' and salary>10000; +----------+ | emp_name | +----------+ | alex | | jinxin | +----------+ #3.關鍵字BETWEEN AND SELECT name,salary FROM employee WHERE salary BETWEEN 10000 AND 20000; SELECT name,salary FROM employee WHERE salary NOT BETWEEN 10000 AND 20000; #注意''是空字串,不是null SELECT name,post_comment FROM employee WHERE post_comment=''; ps: 執行 update employee set post_comment='' where id=2; 再用上條檢視,就會有結果了 #5:關鍵字IN集合查詢 mysql> SELECT name,salary FROM employee WHERE salary=3000 OR salary=3500 OR salary=4000 OR salary=9000 ; +------------+---------+ | name | salary | +------------+---------+ | yuanhao | 3500.00 | | jingliyang | 9000.00 | +------------+---------+ rows in set (0.00 sec) mysql> SELECT name,salary FROM employee WHERE salary IN (3000,3500,4000,9000) ; +------------+---------+ | name | salary | +------------+---------+ | yuanhao | 3500.00 | | jingliyang | 9000.00 | +------------+---------+ mysql> SELECT name,salary FROM employee WHERE salary NOT IN (3000,3500,4000,9000) ; +-----------+------------+ | name | salary | +-----------+------------+ | egon | 7300.33 | | alex | 1000000.31 | | wupeiqi | 8300.00 | | liwenzhou | 2100.00 | | jinxin | 30000.00 | | xiaomage | 10000.00 | | 歪歪 | 3000.13 | | 丫丫 | 2000.35 | | 丁丁 | 1000.37 | | 星星 | 3000.29 | | 格格 | 4000.33 | | 張野 | 10000.13 | | 程咬金 | 20000.00 | | 程咬銀 | 19000.00 | | 程咬銅 | 18000.00 | | 程咬鐵 | 17000.00 | +-----------+------------+ rows in set (0.00 sec) #6:關鍵字LIKE模糊查詢 萬用字元’%’ mysql> SELECT * FROM employee WHERE name LIKE 'jin%'; +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+ | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id | +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+ | 6 | jingliyang | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 | | 7 | jinxin | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 | +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+ rows in set (0.00 sec) 萬用字元'_' mysql> SELECT age FROM employee WHERE name LIKE 'ale_'; +-----+ | age | +-----+ | 78 | +-----+ row in set (0.00 sec) 練習: 1. 檢視崗位是teacher的員工姓名、年齡 2. 檢視崗位是teacher且年齡大於30歲的員工姓名、年齡 3. 檢視崗位是teacher且薪資在9000-1000範圍內的員工姓名、年齡、薪資 4. 檢視崗位描述不為NULL的員工資訊 5. 檢視崗位是teacher且薪資是10000或9000或30000的員工姓名、年齡、薪資 6. 檢視崗位是teacher且薪資不是10000或9000或30000的員工姓名、年齡、薪資 7. 檢視崗位是teacher且名字是jin開頭的員工姓名、年薪 #對應的sql語句 select name,age from employee where post = 'teacher'; select name,age from employee where post='teacher' and age > 30; select name,age,salary from employee where post='teacher' and salary between 9000 and 10000; select * from employee where post_comment is not null; select name,age,salary from employee where post='teacher' and salary in (10000,9000,30000); select name,age,salary from employee where post='teacher' and salary not in (10000,9000,30000); select name,salary*12 from employee where post='teacher' and name like 'jin%'; where約束View Code
2.group by 分組查詢
#1、首先明確一點:分組發生在where之後,即分組是基於where之後得到的記錄而進行的 #2、分組指的是:將所有記錄按照某個相同欄位進行歸類,比如針對員工資訊表的職位分組,或者按照性別進行分組等 #3、為何要分組呢? 取每個部門的最高工資 取每個部門的員工數 取男人數和女人數 小竅門:‘每’這個字後面的欄位,就是我們分組的依據 #4、大前提: 可以按照任意欄位分組,但是分組完畢後,比如group by post,只能檢視post欄位,如果想檢視組內資訊,需要藉助於聚合函式
當執行以下sql語句的時候,是以post欄位查詢了組中的第一條資料,沒有任何意義,因為我們現在想查出當前組的多條記錄。
mysql> select * from employee group by post; +----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+ | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id | +----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+ | 14 | 張野 | male | 28 | 2016-03-11 | operation | NULL | 10000.13 | 403 | 3 | | 9 | 歪歪 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 | | 2 | alex | male | 78 | 2015-03-02 | teacher | | 1000000.31 | 401 | 1 | | 1 | egon | male | 18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使 | NULL | 7300.33 | 401 | 1 | +----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+ rows in set (0.00 sec) #由於沒有設定ONLY_FULL_GROUP_BY,於是也可以有結果,預設都是組內的第一條記錄,但其實這是沒有意義的 如果想分組,則必須要設定全域性的sql的模式為ONLY_FULL_GROUP_BY mysql> set global sql_mode='ONLY_FULL_GROUP_BY'; Query OK, 0 rows affected (0.00 sec) #檢視MySQL 5.7預設的sql_mode如下: mysql> select @@global.sql_mode; +--------------------+ | @@global.sql_mode | +--------------------+ | ONLY_FULL_GROUP_BY | +--------------------+ row in set (0.00 sec) mysql> exit;#設定成功後,一定要退出,然後重新登入方可生效 ByeView Code
繼續驗證通過group by分組之後,只能檢視當前欄位,如果想檢視組內資訊,需要藉助於聚合函式
mysql> select * from emp group by post;# 報錯 ERROR 1054 (42S22): Unknown column 'post' in 'group statement' mysql> select post from employee group by post; +-----------------------------------------+ | post | +-----------------------------------------+ | operation | | sale | | teacher | | 老同安駐沙河辦事處外交大使 | +-----------------------------------------+ rows in set (0.00 sec)
3.聚合函式
max()求最大值 min()求最小值 avg()求平均值 sum() 求和 count() 求總個數 #強調:聚合函式聚合的是組的內容,若是沒有分組,則預設一組 # 每個部門有多少個員工 select post,count(id) from employee group by post; # 每個部門的最高薪水 select post,max(salary) from employee group by post; # 每個部門的最低薪水 select post,min(salary) from employee group by post; # 每個部門的平均薪水 select post,avg(salary) from employee group by post; # 每個部門的所有薪水 select post,sum(salary) from employee group by post;
1. 查詢崗位名以及崗位包含的所有員工名字 2. 查詢崗位名以及各崗位內包含的員工個數 3. 查詢公司內男員工和女員工的個數 4. 查詢崗位名以及各崗位的平均薪資 5. 查詢崗位名以及各崗位的最高薪資 6. 查詢崗位名以及各崗位的最低薪資 7. 查詢男員工與男員工的平均薪資,女員工與女員工的平均薪資 小練習練習
4.HAVING過濾
HAVING與WHERE不一樣的地方在於 #!!!執行優先順序從高到低:where > group by > having #1. Where 發生在分組group by之前,因而Where中可以有任意欄位,但是絕對不能使用聚合函式。 #2. Having發生在分組group by之後,因而Having中可以使用分組的欄位,無法直接取到其他欄位,可以使用聚合函式
驗證: mysql> select * from employee where salary>1000000; +----+------+------+-----+------------+---------+--------------+------------+--------+-----------+ | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id | +----+------+------+-----+------------+---------+--------------+------------+--------+-----------+ | 2 | alex | male | 78 | 2015-03-02 | teacher | | 1000000.31 | 401 | 1 | +----+------+------+-----+------------+---------+--------------+------------+--------+-----------+ 1 row in set (0.00 sec) mysql> select * from employee having salary>1000000; ERROR 1463 (42000): Non-grouping field 'salary' is used in HAVING clause # 必須使用group by才能使用group_concat()函式,將所有的name值連線 mysql> select post,group_concat(name) from emp group by post having salary > 10000; ##錯誤,分組後無法直接取到salary欄位 ERROR 1054 (42S22): Unknown column 'post' in 'field list'驗證
5.limit 限制查詢的記錄數:
示例: SELECT * FROM employee ORDER BY salary DESC LIMIT 3; #預設初始位置為0 SELECT * FROM employee ORDER BY salary DESC LIMIT 0,5; #從第0開始,即先查詢出第一條,然後包含這一條在內往後查5條 SELECT * FROM employee ORDER BY salary DESC LIMIT 5,5; #從第5開始,即先查詢出第6條,然後包含這一條在內往後查5條
# 第1頁資料 mysql> select * from employee limit 0,5; +----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+ | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id | +----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+ | 1 | egon | male | 18 | 2017-03-01 | 老男孩駐沙河辦事處外交大使 | NULL | 7300.33 | 401 | 1 | | 2 | alex | male | 78 | 2015-03-02 | teacher | | 1000000.31 | 401 | 1 | | 3 | wupeiqi | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 | | 4 | yuanhao | male | 73 | 2014-07-01 | teacher | NULL | 3500.00 | 401 | 1 | | 5 | liwenzhou | male | 28 | 2012-11-01 | teacher | NULL | 2100.00 | 401 | 1 | +----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+ rows in set (0.00 sec) # 第2頁資料 mysql> select * from employee limit 5,5; +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+ | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id | +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+ | 6 | jingliyang | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 | | 7 | jinxin | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 | | 8 | xiaomage | male | 48 | 2010-11-11 | teacher | NULL | 10000.00 | 401 | 1 | | 9 | 歪歪 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 | | 10 | 丫丫 | female | 38 | 2010-11-01 | sale | NULL | 2000.35 | 402 | 2 | +----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+ rows in set (0.00 sec) # 第3頁資料 mysql> select * from employee limit 10,5; +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+ | id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id | +----+-----------+--------+-----+------------+-----------+--------------+----------+--------+-----------+ | 11 | 丁丁 | female | 18 | 2011-03-12 | sale | NULL | 1000.37 | 402 | 2 | | 12 | 星星 | female | 18 | 2016-05-13 | sale | NULL | 3000.29 | 402 | 2 | | 13 | 格格 | female | 28 | 2017-01-27 | sale | NULL | 4000.33 | 402 | 2 | | 14 | 張野 | male | 28 | 2016-03-11 | operation | NULL | 10000.13 | 403 | 3 | | 15 | 程咬金 | m