多表查詢
當前的應用系統在存儲數據的時候為了⽅便對數據進⾏管理,都不會將所有的數據存放在⼀個數據庫表中,比如:員⼯的個⼈資料和部門信息是分開存放在不同的表中的,但是員⼯個⼈信息中會標記出其所在的部門。此時在進⾏員⼯信息查詢時,會涉及到多個表;
連接查詢:同時涉及多個表的查詢
連接條件或連接謂詞:用來連接兩個表的條件
⼀般格式:
[表名1.]<列名1> <比較運算符> [表名2.]<列名2>
[表名1.]<列名1> BETWEEN [表名2.]<列名2> AND [表名2.]<列名3>
• 連接條件中的各連接字段類型必須是可比的,但名字不必相同。
常⻅連接查詢
- 內連接
- 外連接
- 復合條件連接
內連接—等值連接
例:查詢每個員⼯所在的部門
內連接的寫法:
第⼀種:使用連接符 =
select * from emp,dept where Dept_id = dept.id;
第⼆種:使用 join .. on..
select * from emp join dept on Dept_id = dept.id;
第三種:使用 inner join .. on..
select * from emp inner join dept on Dept_id = dept.id;
⾮等值連接查詢
員⼯信息表enginfo
⼯資等級表salgrade
select e.ename as '姓名',s.id as '等級' from enginfo e,salgrade s
where e.sal BETWEEN s.local and s.maxline;
⾃身連接
- 自身連接:⼀個表與其自⼰進⾏連接
- 需要給表起別名以示區別
- 由於所有屬性名都是同名屬性,因此必須使用別名前綴
例如:查詢每門課程的先修課名稱
SELECT Qir.cno,Qir.cname, Qir.cpno,sec.cname
FROM course Qir, course sec
WHERE Qir.cpno = sec.cno
外連接
- 外聯接可以是左向外聯接、右向外聯接
- 在 FROM⼦句中指定外聯接時,可以由下列⼏組關鍵字中的⼀組指定:
LEFT JOIN或LEFT OUTER JOIN
RIGHT JOIN 或 RIGHT OUTER JOIN
左連接
- 左向外聯接的結果集包括 LEFT OUTER⼦句中指定的左表的所有⾏,⽽不僅僅是聯接列所匹配的⾏。
- 如果左表的某⾏在右表中沒有匹配⾏,則在相關聯的結果集⾏中右表的所有選擇列表列均為空值。
例:
SELECT s.sno, sname, sex, age, dept, cno, grade
FROM student s LEFT OUT JOIN sc ON s.sno=sc.sno
右連接
右向外聯接是左向外聯接的反向聯接。將返回右表的所有⾏。如果右表的某⾏在左表中沒有匹配⾏,則將為左表返回空值。
外鍵
什么是外鍵:
是另⼀表的主鍵, 外鍵可以有重復的, 可以是空值,用來和其他表建立聯系用的。
主外鍵關系
在上圖上涉及的兩個表中學⽣信息表 (stuInfo)為主表,學⽣成績表(score)為從表;那么主從表之間有什么關系呢?
1、當主表中沒有對應的記錄時,不能將記錄添加到⼦表
學⽣成績表中不能出現學⽣信息表中沒有的學號;
2、不能更改主表中的值⽽導致⼦表中的記錄孤立
學⽣信息表中的id變化了,學⽣成績表中的id也要隨着
發⽣改變;
3、⼦表存在與主表對應的記錄,不能從主表中刪除該⾏
不能把部門表中的數據刪除
4、刪除主表前,先刪⼦表
先刪除成績表、后刪除學⽣信息表;
外鍵的使⽤
外鍵的使用需要滿⾜下列的條件:
1、兩張表必須都是InnoDB表,並且它們沒有臨時表。
2、建立外鍵關系的對應列必須具有相似的InnoDB內部數據類型。
3、建立外鍵關系的對應列必須建立了索引。
創建外鍵的兩種⽅式:
⽅式⼀:在創建表的時候進⾏添加。
⽅式⼆:表已經創建好了,繼續修改表的結構來添加外鍵。
在創建表的時候添加外鍵:
create table stuInfo(
Scode int primary key,-- 學⽣的學號
Sname char(10),-- 學⽣的姓名
Saddress varchar(50),-- 學⽣的住址
Sgrade int,-- 學⽣所在班級
Semail varchar(50),-- 學⽣的郵箱地址
Sbrith date
)DEFAULT CHARSET='utf8';
create table score(
studentID int,
coureseID int,
score int,
scoreID int primary key,
foreign key(studentID) references stuInfo(Scode) -- 添加外鍵
)DEFAULT charset='utf8';
刪除外鍵:
語法:alter table 表名稱 drop foreign key 外鍵名稱;
例:alter table score drop foreign key score_ibQk_1;
注意:如果沒有在建表的時候標明外鍵名稱,可以通過:
show create table 表名 進⾏查看外鍵名稱;
建表以后添加外鍵:
語法:alter table 表名稱 add foreign key (列名稱) references
關聯表名稱(列名稱);
例:alter table stuInfo add foreign key (scode) references
score(studentID);
⼦查詢
- ⼦查詢允許把⼀個查詢嵌套在另⼀個查詢當中。
- ⼦查詢可以包含普通select可以包括的任何⼦句,比如:distinct、 group by、order by、limit、join和union等;但是對應的外部查詢必須是以下語句之⼀:select、insert、update、delete、set或者do。
⼦查詢的分類
- 標量⼦查詢:
返回單⼀值的標量,最簡單的形式。
2.列⼦查詢:
返回的結果集是 N ⾏⼀列。 - ⾏⼦查詢:
返回的結果集是⼀⾏ N 列。 - 表⼦查詢:
返回的結果集是 N ⾏ N 列
可以使用的操作符:= > < >= <= <> ANY IN
SOME ALL EXISTS
標量⼦查詢
是指⼦查詢返回的是單⼀值的標量,如⼀個數字或⼀個字符串,也是⼦查詢中最簡單的返回形式。 可以使用 = > < >= <= <> 這些操作符對⼦查詢的標量結果進⾏比較,通常⼦查詢的位置在比較式的右側
SELECT * FROM article WHERE uid = (SELECT uid FROM user
WHERE status=1 ORDER BY uid DESC LIMIT 1)
SELECT * FROM t1 WHERE column1 = (SELECT MAX(column2) FROM t2)
SELECT * FROM article AS t WHERE 2 = (SELECT COUNT(*) FROM article WHERE article.uid =t.uid)
列⼦查詢
指⼦查詢返回的結果集是 N ⾏⼀列,該結果通常來自對表的某個字段查詢返回。
可以使用 IN、ANY和 ALL 操作符
SELECT * FROM article WHERE uid IN(SELECT uid FROM user WHERE status=1)
SELECT s1 FROM table1 WHERE s1 > ANY (SELECT s2 FROM table2)
SELECT s1 FROM table1 WHERE s1 > ALL (SELECT s2 FROM table2)
⾏⼦查詢
指⼦查詢返回的結果集是⼀⾏ N 列,該⼦查詢的結果通常是對表的某⾏數據進⾏查詢⽽返回的結果集。
SELECT * FROM article WHERE (title,content,uid) =
(SELECT title, content,uid FROM blog WHERE bid=2)
表⼦查詢
指⼦查詢返回的結果集是 N ⾏ N 列的⼀個表數據。
SELECT * FROM article WHERE (title, content, uid)
IN (SELECT title, content, uid FROM blog)
EXIST謂詞
EXISTS是⼀個非常⽜叉的謂詞,它允許數據庫⾼效地檢查指定查詢是否產⽣某些⾏。
select * from t1 where city=‘beijing' and exists
(select * from t2 where t1.cid=t2.cid);
派⽣表
在⼦查詢返回的值中,也可能返回⼀個表,如果將⼦查詢返回的虛擬表再次作為FROM⼦句的輸⼊時,這就⼦查詢的虛擬表就成為了⼀個派⽣表。
FROM (subquery expression) AS derived_table_alias
派⽣表使⽤
派⽣表⼀般與外連接,分組統計⼀起使用
SELECT t1.name,t2.sex,a.city,a.age FROM t1,
(SELECT city, MAX(age) FROM t2 GROUP BY city) a
WHERE t1.age=t2.age;
聯合查詢
使用UNION或UNION ALL關鍵字
相同結果被篩選掉了
SELECT cname,sex FROM users
UNION
SELECT name,sex FROM teacher;
有ALL,保留相同項
SELECT cname,sex FROM users
UNION ALL
SELECT name,sex FROM teacher;