Linux-數據庫3
阿新 • • 發佈:2017-08-14
包含 mar employ sel all 多表 一致性 刪除外鍵 基礎
外鍵約束
如果表A的主關鍵字是表B中的字段,則該字段稱為表B的外鍵,表A稱為主表,表B稱為從表。
外鍵是用來實現參照完整性的,不同的外鍵約束方式將可以使兩張表緊密的結合起來,特別是修改或者刪除的級聯操作。外鍵主要用來保證數據的完整性和一致性。
兩個表必須是InnoDB表,MyISAM表暫時不支持外鍵。
外鍵關系的兩個表的列必須是數據類型相似,也就是可以相互轉換類型的列,比如int和tinyint可以,而int和char則不可以。
創建外鍵
#每一個班主任會對應多個學生 , 而每個學生只能對應一個班主任 #主表 CREATE TABLE ClassCharger( id TINYINT PRIMARY KEY auto_increment, name VARCHAR (20), age INT , is_marriged boolean -- show create table ClassCharger: tinyint(1) ); INSERT INTO ClassCharger (name,age,is_marriged) VALUES ("冰冰",12,0), ("丹丹",14,0), ("歪歪",22,0), ("姍姍",20,0), ("小雨",21,0); #子表 CREATE TABLE Student( id INT PRIMARY KEY auto_increment, name VARCHAR (20), charger_id TINYINT, --切記:作為外鍵一定要和關聯主鍵的數據類型保持一致 -- [ADD CONSTRAINT charger_fk_stu]FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) #創建關聯 ) ENGINE=INNODB; INSERT INTO Student(name,charger_id) VALUES ("alvin1",2), ("alvin2",4), ("alvin3",1), ("alvin4",3), ("alvin5",1), ("alvin6",3), ("alvin7",2); DELETE FROM ClassCharger WHERE name="冰冰"; INSERT student (name,charger_id) VALUES ("yuan",1); -- 刪除居然成功,可是 alvin3顯示還是有班主任id=1的冰冰的; -----------增加外鍵和刪除外鍵--------- ALTER TABLE student ADD CONSTRAINT abc FOREIGN KEY(charger_id) REFERENCES classcharger(id); ALTER TABLE student DROP FOREIGN KEY abc;
INNODB支持的ON語句
--外鍵約束對子表的含義: 如果在父表中找不到候選鍵,則不允許在子表上進行insert/update --外鍵約束對父表的含義: 在父表上進行update/delete以更新或刪除在子表中有一條或多條對 -- 應匹配行的候選鍵時,父表的行為取決於:在定義子表的外鍵時指定的 -- on update/on delete子句 -----------------innodb支持的四種方式--------------------------------------- -----cascade方式 在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄 -----外鍵的級聯刪除:如果父表中的記錄被刪除,則子表中對應的記錄自動被刪除-------- FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE CASCADE ------set null方式 在父表上update/delete記錄時,將子表上匹配記錄的列設為null -- 要註意子表的外鍵列不能為not null FOREIGN KEY (charger_id) REFERENCES ClassCharger(id) ON DELETE SET NULL ------Restrict方式 :拒絕對父表進行刪除更新操作(了解) ------No action方式 在mysql中同Restrict,如果子表中有匹配的記錄,則不允許對父表對應候選鍵 -- 進行update/delete操作(了解)
多表查詢
準備表
-- 準備兩張表 -- company.employee -- company.department create table employee( emp_id int auto_increment primary key not null, emp_name varchar(50), age int, dept_id int ); insert into employee(emp_name,age,dept_id) values (‘A‘,19,200), (‘B‘,26,201), (‘C‘,30,201), (‘D‘,24,202), (‘E‘,20,200), (‘F‘,38,204); create table department( dept_id int, dept_name varchar(100) ); insert into department values (200,‘人事部‘), (201,‘技術部‘), (202,‘銷售部‘), (203,‘財政部‘); mysql> select * from employee; +--------+----------+------+---------+ | emp_id | emp_name | age | dept_id | +--------+----------+------+---------+ | 1 | A | 19 | 200 | | 2 | B | 26 | 201 | | 3 | C | 30 | 201 | | 4 | D | 24 | 202 | | 5 | E | 20 | 200 | | 6 | F | 38 | 204 | +--------+----------+------+---------+ 6 rows in set (0.00 sec) mysql> select * from department; +---------+-----------+ | dept_id | dept_name | +---------+-----------+ | 200 | 人事部 | | 201 | 技術部 | | 202 | 銷售部 | | 203 | 財政部 | +---------+-----------+ 4 rows in set (0.01 sec)
連接查詢
1、迪爾卡積查詢:這種查詢本身是沒有意義的
mysql> SELECT * FROM employee,department; -- select employee.emp_id,employee.emp_name,employee.age, -- department.dept_name from employee,department; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 1 | A | 19 | 200 | 201 | 技術部 | | 1 | A | 19 | 200 | 202 | 銷售部 | | 1 | A | 19 | 200 | 203 | 財政部 | | 2 | B | 26 | 201 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 2 | B | 26 | 201 | 202 | 銷售部 | | 2 | B | 26 | 201 | 203 | 財政部 | | 3 | C | 30 | 201 | 200 | 人事部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 202 | 銷售部 | | 3 | C | 30 | 201 | 203 | 財政部 | | 4 | D | 24 | 202 | 200 | 人事部 | | 4 | D | 24 | 202 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 4 | D | 24 | 202 | 203 | 財政部 | | 5 | E | 20 | 200 | 200 | 人事部 | | 5 | E | 20 | 200 | 201 | 技術部 | | 5 | E | 20 | 200 | 202 | 銷售部 | | 5 | E | 20 | 200 | 203 | 財政部 | | 6 | F | 38 | 204 | 200 | 人事部 | | 6 | F | 38 | 204 | 201 | 技術部 | | 6 | F | 38 | 204 | 202 | 銷售部 | | 6 | F | 38 | 204 | 203 | 財政部 | +--------+----------+------+---------+---------+-----------+
2、內連接
-- 查詢兩張表中都有的關聯數據,相當於利用條件從笛卡爾積結果中篩選出了正確的結果。 select * from employee,department where employee.dept_id = department.dept_id; --select * from employee inner join department on employee.dept_id = department.dept_id;(推薦使用方法) +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 5 | E | 20 | 200 | 200 | 人事部 | +--------+----------+------+---------+---------+-----------+
3、外連接
--(1)左外連接:在內連接的基礎上增加左邊有右邊沒有的結果 select * from employee left join department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 5 | E | 20 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 6 | F | 38 | 204 | NULL | NULL | +--------+----------+------+---------+---------+-----------+ --(2)右外連接:在內連接的基礎上增加右邊有左邊沒有的結果 select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 5 | E | 20 | 200 | 200 | 人事部 | | NULL | NULL | NULL | NULL | 203 | 財政部 | +--------+----------+------+---------+---------+-----------+ --(3)全外連接:在內連接的基礎上增加左邊有右邊沒有的和右邊有左邊沒有的結果 -- mysql不支持全外連接 full JOIN -- mysql可以使用此種方式間接實現全外連接 select * from employee RIGHT JOIN department on employee.dept_id = department.dept_id UNION select * from employee LEFT JOIN department on employee.dept_id = department.dept_id; +--------+----------+------+---------+---------+-----------+ | emp_id | emp_name | age | dept_id | dept_id | dept_name | +--------+----------+------+---------+---------+-----------+ | 1 | A | 19 | 200 | 200 | 人事部 | | 2 | B | 26 | 201 | 201 | 技術部 | | 3 | C | 30 | 201 | 201 | 技術部 | | 4 | D | 24 | 202 | 202 | 銷售部 | | 5 | E | 20 | 200 | 200 | 人事部 | | NULL | NULL | NULL | NULL | 203 | 財政部 | | 6 | F | 38 | 204 | NULL | NULL | +--------+----------+------+---------+---------+-----------+ -- 註意 union與union all的區別:union會去掉相同的紀錄
4、復合條件連接查詢
-- 查詢員工年齡大於等於25歲的部門 SELECT DISTINCT department.dept_name FROM employee,department WHERE employee.dept_id = department.dept_id AND age>25; --以內連接的方式查詢employee和department表,並且以age字段的升序方式顯示 select employee.emp_id,employee.emp_name,employee.age,department.dept_name from employee,department where employee.dept_id = department.dept_id order by age asc;
5、子查詢(嵌套查詢)
-- 子查詢是將一個查詢語句嵌套在另一個查詢語句中。 -- 內層查詢語句的查詢結果,可以為外層查詢語句提供查詢條件。 -- 子查詢中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字 -- 還可以包含比較運算符:= 、 !=、> 、<等 -- 1. 帶IN關鍵字的子查詢 ---查詢employee表,但dept_id必須在department表中出現過 select * from employee where dept_id IN (select dept_id from department); +--------+----------+------+---------+ | emp_id | emp_name | age | dept_id | +--------+----------+------+---------+ | 1 | A | 19 | 200 | | 2 | B | 26 | 201 | | 3 | C | 30 | 201 | | 4 | D | 24 | 202 | | 5 | E | 20 | 200 | +--------+----------+------+---------+ 5 rows in set (0.01 sec) -- 2. 帶比較運算符的子查詢 -- =、!=、>、>=、<、<=、<> -- 查詢員工年齡大於等於25歲的部門 select dept_id,dept_name from department where dept_id IN (select DISTINCT dept_id from employee where age>=25); -- 3. 帶EXISTS關鍵字的子查詢 -- EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。 -- 而是返回一個真假值。Ture或False -- 當返回Ture時,外層查詢語句將進行查詢;當返回值為False時,外層查詢語句不進行查詢 select * from employee WHERE EXISTS (SELECT dept_name from department where dept_id=203); --department表中存在dept_id=203,Ture select * from employee WHERE EXISTS (SELECT dept_name from department where dept_id=205); -- Empty set (0.00 sec) ps: create table t1(select * from t2);
Linux-數據庫3