MySQL數據庫(四)多表查詢


兩張假設有兩張表格A和B,把表格當作一個集合,那么表格中的記錄就是集合中的一個元素。

兩張表格如下:

TableA:TableB:

2.1 內連接(只有一種場景)

inner join 或者join(等同於inner join)

 

  1.  
    select a.*, b.* from tablea a
  2.  
    inner join tableb b
  3.  
    on a.id = b.id

 

 

  1.  
    select a.*, b.* from tablea a
  2.  
    join tableb b
  3.  
    on a.id = b.id

 

結果如下:

應用場景:

這種場景下得到的是滿足某一條件的A,B內部的數據;正因為得到的是內部共有數據,所以連接方式稱為內連接。

2.2 外連接(六種場景)

2.2.1 left join 或者left outer join(等同於left join)

  1.  
    select a.*, b.* from tablea a
  2.  
    left join tableb b
  3.  
    on a.id = b.id

 

或者

 

  1.  
    select a.*, b.* from tablea a
  2.  
    left outer join tableb b
  3.  
    on a.id = b.id

結果如下,TableB中更不存在的記錄填充Null:

應用場景:


這種場景下得到的是A的所有數據,和滿足某一條件的B的數據;

2.2.2  [left   join 或者left outer join(等同於left join)]  +  [where B.column is null]

 

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    left join tableb b
  3.  
    on a.id = b.id
  4.  
    Where b.id is null

結果如下:


應用場景:

這種場景下得到的是A中的所有數據減去"與B滿足同一條件 的數據",然后得到的A剩余數據;

2.2.3  right join 或者fight outer join(等同於right join)

 

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    right join tableb b
  3.  
    on a.id = b.id

結果如下,TableB中更不存在的記錄填充Null:

 

應用場景:

這種場景下得到的是B的所有數據,和滿足某一條件的A的數據;

2.2.4 [left   join 或者left outer join(等同於left join)]  +  [where A.column is null]

 

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    right join tableb b
  3.  
    on a.id = b.id
  4.  
    where a.id is null

結果如下:

 


應用場景:

這種場景下得到的是B中的所有數據減去 "與A滿足同一條件 的數據“,然后得到的B剩余數據;

2.2.5 full join (mysql不支持,但是可以用 left join  union right join代替)

 

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    left join tableb b
  3.  
    on a.id = b.id
  4.  
    union
  5.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  6.  
    right join tableb b
  7.  
    on a.id = b.id

union過后,重復的記錄會合並(id為2,3,4的三條記錄),所以結果如下:

 

應用場景:

 

這種場景下得到的是滿足某一條件的公共記錄,和獨有的記錄

2.2.6 full join + is null(mysql不支持,但是可以用 (left join + is null) union (right join+isnull代替)

 

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    left join tableb b
  3.  
    on a.id = b.id
  4.  
    where b.id is null
  5.  
    union
  6.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  7.  
    right join tableb b
  8.  
    on a.id = b.id
  9.  
    where a.id is null

結果如下:

 

應用場景:

這種場景下得到的是A,B中不滿足某一條件的記錄之和

注:上面共有其中七(2^3-1)種應用場景,還有一種是全空白,那就是什么都不查,七種情形包含了實際應用所有可能的場景

2.3 交叉連接 (cross join)

2.3.1 實際應用中還有這樣一種情形,想得到A,B記錄的排列組合,即笛卡兒積,這個就不好用集合和元素來表示了。需要用到cross join:

 

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    cross join tableb b

 

2.3.2 還可以為cross  join指定條件 (where):

  1.  
    select a.id aid,a.age,b.id bid,b.name from tablea a
  2.  
    cross join tableb b
  3.  
    where a.id = b.id

結果如下;

注:這種情況下實際上實現了內連接的效果

三 注意事項

上面仍然存在遺漏,那就是mysql對sql語句的容錯問題,即在sql語句不完全符合書寫建議的情況,mysql會允許這種情況,盡可能地解釋它:

3.1 一般cross join后面加上where條件,但是用cross join+on也是被解釋為cross join+where;

3.2 一般內連接都需要加上on限定條件,如上面場景2.1;如果不加會被解釋為交叉連接;

3.3 如果連接表格使用的是逗號,會被解釋為交叉連接;

注:sql標准中還有union join和natural  inner join,mysql不支持,而且本身也沒有多大意義,其結果可以用上面的幾種連接方式得到

 

外鍵約束:

創建新聞分類表:news_cate

CREATE TABLE news_cate(

id TINYINT UNSIGNED AUTO_INCREMENT KEY,

cate_name  VARCHAR(50) NOT NULL UNIQUE,

cate_desc VARCHAR(100)  NOT NULL DEFAULT ' '

);

創建新聞表:news

CREATE TABLE news(

id INT UNSIGNED AUTO_INCREMENT KEY,

title VARCHAR(100) NOT NULL UNIQUE,

content VARCHAR(100) NOT NULL,

cate_id TINYINT UNSIGNED NOT NULL

);  

創建成功以后,我們插入一些記錄.

INSERT INTO news_cate(cate_name) values('chineses news'),('glocal news'),('sports news'),('entertainment news');

INSERT INTO news(title,content,cate_id) VALUES('a1','aaa1',1),('a2','aaa2',2),('a3','aaa3',3),('a4','aaa4',4),('a5','aaa5',15);   

查詢news表中的id title content,news_cate表中的cate_name   

(用到我們剛剛學到的多表聯查)

SELECT n.id,n.title,n.content,c.cate_name from news AS n

JOIN news_cate AS c

ON n.cate_id = c.id;

這時候news_cate新聞分類中,去掉了國際新聞

DELETE FROM news_cate where id = 2;

成功刪除了,但是我們再看看新聞表news,表中的cate_id還有2,顯然這是不合適的

INSERT INTO news(title,content,cate_id) VALUES('a6','aaa6',45);

這條數據也插進去了,這兩個記錄的cate_id,都不在新聞分類里面,這就是所謂的臟數據,此時我們就要用外鍵,來保持數據的一致性和完整性.

創建外鍵的兩種方法:

  1 建表時指定外鍵盤:FOREIGN KEY(字段名) REFERENCES 主表(字段名)

    注意:子表關聯的必須是父表的主鍵

  2動態添加外鍵

    ALTER TABLE 表名 drop foreign key 外鍵名

      ALTER TABLE 表名 ADD FOREIGN KEY(外鍵字段) REFERENCES 主表(主鍵字段);

    **注意,動態添加外鍵時,不能有臟數據,否則不能成功添加外鍵

所以為了自動去掉臟數據,我們把新聞表news刪掉,重新建有外鍵的news表

CREATE TABLE news(

id INT UNSIGNED AUTO_INCREMENT KEY,

title VARCHAR(100) NOT NULL UNIQUE,

content VARCHAR(100) NOT NULL,

cate_id TINYINT UNSIGNED NOT NULL,

FOREIGN KEY(cate_id) REFERENCES news_cate(id)

);  

重新插入一下數據,現在非法記錄就不可以插入了,這就是有外鍵和無外鍵的區別和約束

INSERT INTO news(title,content,cate_id) VALUES('a1','aaa1',1),('a2','aaa2',1),('a3','aaa3',3),('a4','aaa4',4),('a5','aaa5',3);

 

 

 

 

 

 

 

參考連接:https://blog.csdn.net/jintao_ma/article/details/51260458


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM