數據庫Ⅵ——連接查詢(外鍵、聯合查詢)

一、外鍵的介紹

  1. 外鍵是表的一個特殊字段。被參照的表是主表,外鍵所在字段的表爲子表。設置外鍵的原則需要記住,就是依賴於數據庫中已存在的表的主鍵。外鍵的作用是建立該表與其父表的關聯關係。父表中對記錄做操作時,子表中與之對應的信息也應有相應的改變。
  2. 外鍵的作用保持數據的一致性和完整性
  3. 可以實現一一對一或一對多的關係
  4. 注意
    • 父表和子表必須使用相同的存儲引擎,而且禁止使用臨時表。
    • 數據表的存儲引擎只能爲InnoDB。
    • 外鍵列和參照列必須具有相似的數據類型。其中數字的長度或是否有符號位必須相同;而字符的長度則可以不同。
    • 外鍵列和參照列必須創建索引。如果外鍵列不存在索引的話,MySQL將自動創建索引。
  5. 外鍵約束的參照操作
    • CASCADE:從父表刪除或更新且自動刪除或更新子表中匹配的行。
    • SET NULL:從父表刪除或更新行,並設置子表中的外鍵列爲NULL。如果使用該選項,必須保證子表列沒有指定NOT NULL。
    • RESTRICT:拒絕對父表的刪除或更新操作。
    • NO ACTION :標準SQL的關鍵字,在MySQL中與 RESTRICT相同

二、測試外鍵

1.首先嚐試內連接方式

  • 創建部門表department(主表);id depName
CREATE TABLE IF NOT EXISTS department(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
depName VARCHAR(20) NOT NULL UNIQUE
)ENGINE=INNODB;
INSERT department(depName) VALUES('教學部'),
('市場部'),
('運營部'),
('督導部');
  • 創建員工表employee(子表);id ,username ,depId
CREATE TABLE IF NOT EXISTS employee(
id SMALLINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
depId TINYINT UNSIGNED
)ENGINE=INNODB;
INSERT employee(username,depId) VALUES('king',1),
('queen',2),
('張三',3),
('李四',4),
('王五',1);
  • 利用內連接將員工與所屬部門匹配
SELECT e.id,e.username,d.depName FROM
employee AS e
JOIN
department AS d
ON e.depId=d.id;

2.內連接的侷限性

  • 刪除督導部
DELETE FROM department WHERE depName='督導部';

雖然‘督導部’現在已經沒有了,但是查詢的時候,李四仍然在4部門,也就是對應的督導部。由此,可以看出內連接方式的一致性並不是很好

mysql> SELECT * FROM employee;
+----+----------+-------+
| id | username | depId |
+----+----------+-------+
|  1 | king     |     1 |
|  2 | queen    |     2 |
|  3 | 張三         |     3 |
|  4 | 李四         |     4 |
|  5 | 王五         |     1 |

3.外鍵的使用

  • 創建部門表department(主表);id depName
CREATE TABLE IF NOT EXISTS department(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
depName VARCHAR(20) NOT NULL UNIQUE
)ENGINE=INNODB;
INSERT department(depName) VALUES('教學部'),
('市場部'),
('運營部'),
('督導部');

(1)加入外鍵 FOREIGN KEY

  • 創建員工表employee(子表);id ,username ,depId
CREATE TABLE IF NOT EXISTS employee(
id SMALLINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
depId TINYINT UNSIGNED,
FOREIGN KEY(depId) REFERENCES department(id)
)ENGINE=INNODB;
INSERT employee(username,depId) VALUES('king',1),
('queen',2),
('張三',3),
('李四',4),
('王五',1);

(2)直接刪除主表記錄失敗

  • 刪除主表中的記錄
DELETE FROM department WHERE id=1;

mysql> DELETE FROM department WHERE id=1;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`cms`.`employee`, CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`depId`) REFERENCES `department` (`id`))

(3)先對子表進行操作

  • 刪除employee中的屬於1部門的人
DELETE FROM employee WHERE depId=1;
  • 接下來在刪除 id=1 的部門就能成功了
DELETE FROM department WHERE id=1;

mysql> SELECT * FROM department;
+----+---------+
| id | depName |
+----+---------+
|  2 | 市場部       |
|  4 | 督導部        |
|  3 | 運營部       |
+----+---------+

(4)測試插入錯誤數據

depId=11不在範圍內,插入失敗

INSERT employee(username,depId) VALUES('test',11);
mysql> INSERT employee(username,depId) VALUES('test',11);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`cms`.`employee`, CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`depId`) REFERENCES `department` (`id`))

三、外鍵的添加刪除

  • 刪除員工表
DROP TABLE employee;
  • 重新創建
CREATE TABLE IF NOT EXISTS cms.employee(
id SMALLINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
depId TINYINT UNSIGNED,
CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id)
)ENGINE=INNODB;
INSERT employee(username,depId) VALUES('king',3),
('queen',2),
('張三',3),
('李四',4),
('王五',2);

1.刪除外鍵

ALTER TABLE employee DROP FOREIGN KEY emp_fk_dep;

2.添加外鍵

  • 刪除id=2
DELETE FROM department WHERE id=2;
  • 添加外鍵失敗
ALTER TABLE employee ADD CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id);
提示錯誤:
mysql> ALTER TABLE employee ADD CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`cms`.`#sql-f18_7`, CONSTRAINT `emp_fk_dep` FOREIGN KEY (`depId`) REFERENCES `department` (`id`))

  • 刪除對應的depId=2,成功
mysql> DELETE FROM employee WHERE depId=2;
ALTER TABLE employee ADD CONSTRAINT emp_fk_dep FOREIGN KEY(depId) REFERENCES department(id);

3.測試 CASCADE

  • 刪除之前的表,重新創建employee和department
CREATE TABLE IF NOT EXISTS department(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
depName VARCHAR(20) NOT NULL UNIQUE
)ENGINE=INNODB;
INSERT department(depName) VALUES('教學部'),
('市場部'),
('運營部'),
('督導部');
#創建員工表employee(子表);id ,username ,depId
CREATE TABLE IF NOT EXISTS employee(
id SMALLINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
depId TINYINT UNSIGNED,
FOREIGN KEY(depId) REFERENCES department(id) ON DELETE CASCADE ON UPDATE CASCADE

#對刪除和更新操作都應用CASCADE

)ENGINE=INNODB;
INSERT employee(username,depId) VALUES('king',1),
('queen',2),
('張三',3),
('李四',4),
('王五',1);
  • 刪除部門表中的第一個部門
DELETE FROM department WHERE id=1;

結果:department和employee中對應的部分和部分中的員工都被刪除了

mysql> SELECT * FROM department;
+----+---------+
| id | depName |
+----+---------+
|  2 | 市場部       |
|  4 | 督導部        |
|  3 | 運營部       |
+----+---------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM employee;
+----+----------+-------+
| id | username | depId |
+----+----------+-------+
|  2 | queen    |     2 |
|  3 | 張三         |     3 |
|  4 | 李四         |     4 |
+----+----------+-------+
3 rows in set (0.00 sec)
  • 更新id
UPDATE department SET id=id+10;

4.測試 SET NULL

  • 刪除之前的表,重新創建employee和department
CREATE TABLE IF NOT EXISTS department(
id TINYINT UNSIGNED AUTO_INCREMENT KEY,
depName VARCHAR(20) NOT NULL UNIQUE
)ENGINE=INNODB;
INSERT department(depName) VALUES('教學部'),
('市場部'),
('運營部'),
('督導部');

CREATE TABLE IF NOT EXISTS employee(
id SMALLINT UNSIGNED AUTO_INCREMENT KEY,
username VARCHAR(20) NOT NULL UNIQUE,
depId TINYINT UNSIGNED,
FOREIGN KEY(depId) REFERENCES department(id) ON DELETE SET NULL ON UPDATE SET NULL

#刪除和更新操作都加入SET NULL  

)ENGINE=INNODB;
INSERT employee(username,depId) VALUES('king',1),
('queen',2),
('張三',3),
('李四',4),
('王五',1);
  • 刪除id=1
DELETE FROM department WHERE id=1;

結果:king和王五對應的depId變爲NULL
mysql> SELECT * FROM employee;
+----+----------+-------+
| id | username | depId |
+----+----------+-------+
|  1 | king     |  NULL |
|  2 | queen    |     2 |
|  3 | 張三         |     3 |
|  4 | 李四         |     4 |
|  5 | 王五         |  NULL |
+----+----------+-------+
5 rows in set (0.00 sec)

四、聯合查詢

1.簡介

  • UNION
  • UNION ALL
  • UNION和IUNION ALL區別是UNION去掉相同記錄,UION ALL是簡單的合併到一起。

2.測試 UNION

SELECT username FROM employee UNION SELECT username FROM cms_user;

employee中有5條記錄,cms_user中有12條記錄,但是查詢結果是15條,因爲有兩條記錄重複

3.測試 UNION ALL

SELECT username FROM employee UNION ALL SELECT username FROM cms_user;

因爲UION ALL是簡單的合併到一起,所以查詢結果可以重複,共有17條

4.字段個數需匹配

  • 字段個數不匹配時會報錯
SELECT id,username FROM employee UNION ALL SELECT username FROM cms_user;
報錯:
mysql> SELECT id,username FROM employee UNION ALL SELECT username FROM cms_user;
ERROR 1222 (21000): The used SELECT statements have a different number of columns
  • 只要字段個數匹配就行
SELECT id,username FROM employee UNION ALL SELECT username,age FROM cms_user;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章