MySQL多表操作(一對一 一對多 多對多)


  參考:https://blog.csdn.net/zuosixiaonengshou/article/details/53011452

  一,1對1

  1方建主表(id為主鍵字段), 一方或多方建外鍵字段(參考主表的主鍵id,加unique)

  示例:一個女人(woman)對應一個丈夫(man)不能對應多個丈夫,一個丈夫也不能對應多個女人,妻子

  創建man表(建表前創建一個test庫)

mysql> create table man(
 id varchar(32) primary key , 
name varchar(30) 
);

   創建woman表

mysql> create table woman( 
id varchar(32) primary key , 
name varchar(30), 
husband varchar(32) unique, 
constraint wm_fk foreign key(husband) references man(id) 
);

   建表語句解析

unique # 設置約束 才是1對1否則為1對多
constraint wm_fk foreign key(husband) references man(id) #創建外鍵名為wm_fk 本表字段husband關聯表man的id字段

   查看建表語句

 

   一一對應關系

 

   插入數據

  首先插入3個男人

mysql> insert into man values('1', '小明');
Query OK, 1 row affected (0.00 sec)

mysql> insert into man values('2', '小聰');
Query OK, 1 row affected (0.01 sec)

mysql> insert into man values('3', '老王');
Query OK, 1 row affected (0.00 sec)

 

 

   插入女人並設置對應丈夫關系

mysql> insert into woman values('1', '小花', 2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into woman values('2', '小靜', 1);
Query OK, 1 row affected (0.00 sec)

   以下插入報錯

 

   husband可以為空代表為單身狗

mysql> insert into woman values('3', '小紅', null);

   查看數據

   查詢夫妻信息

mysql> SELECT man.name AS 丈夫, woman.name AS 妻子 FROM man INNER JOIN woman ON man.id=woman.husband;

   當man.id和woman.huaband相同時查詢數據即顯示丈夫和妻子對應信息

   查詢語句解析

SELECT man.name AS 丈夫, woman.name AS 妻子 # 把表man的name字段以丈夫顯示 woman的name字段以妻子顯示 
FROM man INNER JOIN woman # 內聯查詢查詢兩個表有值相同的字段 
ON man.id=woman.husband;    # 設置查詢條件即woman的husband字段和man的id字段相同的則滿足條件即夫妻的一對一關系

    查詢小花的丈夫是誰

mysql> SELECT man.name AS 丈夫, woman.name AS 妻子 FROM man INNER JOIN woman ON woman.name='小花' and man.id=woman.husband;

   注意:需要加and同時滿足條件man.id=woman.husband 否則會在表man查詢出3跳數據

 

 

   二,1對多

  1方建主表(id為主鍵字段), 一方或多方建外鍵字段(參考主表的主鍵id,不加unique)

  創建人員表

CREATE TABLE `person2` (
  `id` varchar(32) primary key,
  `name` varchar(30),
  `sex` char(1),
);

  創建對應汽車表,外鍵為pid連接表person2的主鍵id 外鍵未加unique參數代表一個car可以對應多個person即多輛汽車可以對應1個人即一個人可以擁有多輛汽車

REATE TABLE `car` (
  `id` varchar(32) PRIMARY KEY,
  `name` varchar(30),
  `price` decimal(10,2),
  `pid` varchar(32) ,
  CONSTRAINT `car_fk` FOREIGN KEY (`pid`) REFERENCES `person2` (`id`)
)

   插入數據 

  首先插入人員數據

mysql> insert into person2 values('P01', 'Jack', 1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into person2 values('P02', 'Tom', 1);
Query OK, 1 row affected (0.00 sec)

mysql> insert into person2 values('P03', 'Rose', 0);
Query OK, 1 row affected (0.01 sec)

 

 

   插入汽車數據

# C001 002 003屬於人P01
mysql> insert into car values('C001', 'BMW', 30, 'P01');
Query OK, 1 row affected (0.01 sec)

mysql> insert into car values('C002', 'BEnZ', 40, 'P01');
Query OK, 1 row affected (0.00 sec)

mysql> insert into car values('C003', 'Audi', 40, 'P01');
Query OK, 1 row affected (0.00 sec)
# C004屬於人員P02
mysql> insert into car values('C004', 'QQ', 5.5, 'P02');
Query OK, 1 row affected (0.00 sec)

# 也可以插入兩輛汽車不屬於任何人
mysql> insert into car values('C005', 'ABC', 10, null);
Query OK, 1 row affected (0.00 sec)

mysql> insert into car values('C006', 'BCD', 10, null);
Query OK, 1 row affected (0.44 sec)

 

 

   查詢那些人有那些車

mysql> select person2.name, car.name from person2 inner join car on person2.id=car.pid;
+------+------+
| name | name |
+------+------+
| Jack | BMW  |
| Jack | BEnZ |
| Jack | Audi |
| Tom  | QQ   |
+------+------+
4 rows in set (0.00 sec)

   查詢Jack有哪些車

mysql> select person2.name, car.name from person2 inner join car on person2.id=car.pid and person2.name='Jack';

+------+------+
| name | name |
+------+------+
| Jack | BMW  |
| Jack | BEnZ |
| Jack | Audi |
+------+------+
3 rows in set (0.00 sec)

   注意:這里條件也可以使用where

mysql> select person2.name, car.name from person2 inner join car on person2.id=car.pid where person2.name='Jack';
+------+------+
| name | name |
+------+------+
| Jack | BMW  |
| Jack | BEnZ |
| Jack | Audi |
+------+------+
3 rows in set (0.00 sec)

   查詢誰有兩輛及兩輛以上的汽車

mysql> SELECT person2.name, car.NAME,car.price  FROM car   INNER JOIN person2 ON car.pid=person2.id WHERE personn2.id IN(      SELECT pid FROM car GROUP BY pid HAVING COUNT(pid)>=2   );
+------+------+-------+
| name | NAME | price |
+------+------+-------+
| Jack | BMW  | 30.00 |
| Jack | BEnZ | 40.00 |
| Jack | Audi | 40.00 |
+------+------+-------+
3 rows in set (0.00 sec)

   其中語句把兩輛汽車以上的pid取到,然后在使用person2.id進行匹配

 SELECT pid FROM car GROUP BY pid HAVING COUNT(pid)>=2;

 

 

   演示左關聯

mysql> select * from person2 left join car on car.pid=person2.id;
+-----+------+------+------+------+-------+------+
| id  | name | sex  | id   | name | price | pid  |
+-----+------+------+------+------+-------+------+
| P01 | Jack | 1    | C001 | BMW  | 30.00 | P01  |
| P01 | Jack | 1    | C002 | BEnZ | 40.00 | P01  |
| P01 | Jack | 1    | C003 | Audi | 40.00 | P01  |
| P02 | Tom  | 1    | C004 | QQ   |  5.50 | P02  |
| P03 | Rose | 0    | NULL | NULL |  NULL | NULL |
+-----+------+------+------+------+-------+------+
5 rows in set (0.00 sec)

   左關聯得到左邊表全部數據以及滿足某一條件的右邊表數據,如果不存在則填充null

  由全表可知只需條件是car.id或NAME或price或pid為空即可查出誰沒有車

  查詢那些人沒有車

mysql> select person2.name from person2 left join car on car.pid=person2.id where car.name is null;
+------+
| name |
+------+
| Rose |
+------+
1 row in set (0.00 sec)

   其實右關聯跟左關聯一樣,只需要把左關聯的表調換一下位置便成了右關聯的結果,所以只要會了左關聯,右關聯也是一樣的。

  使用右連接查詢那些車沒有賣出去

mysql> select * from person2 right join car on car.pid=person2.id where person2.id is null;
+------+------+------+------+------+-------+------+
| id   | name | sex  | id   | name | price | pid  |
+------+------+------+------+------+-------+------+
| NULL | NULL | NULL | C005 | ABC  | 10.00 | NULL |
| NULL | NULL | NULL | C006 | BCD  | 10.00 | NULL |
+------+------+------+------+------+-------+------+
2 rows in set (0.00 sec)

mysql> select car.name from person2 right join car on car.pid=person2.id where person2.id is null;
+------+
| name |
+------+
| ABC  |
| BCD  |
+------+
2 rows in set (0.00 sec)

   

  三, 多對多

  兩個實體都建成獨立的主表, 另外再單獨建一個關系表(采用聯合主鍵)

  1、分別建議兩個實體表(沒有外鍵,但有自己的主鍵, 沒有冗余信息)

//DROP TABLE stud;
//學生表
CREATE TABLE stud(
  id VARCHAR(32) PRIMARY KEY,
  NAME VARCHAR(30)
);
//課程表
CREATE TABLE ject(
  id VARCHAR(32) PRIMARY KEY,
  NAME VARCHAR(30)
);

   2,另外補建一個關系表

CREATE TABLE sj(
  studid VARCHAR(32) NOT NULL,
  jectid VARCHAR(32)
);
//注意,要先建聯合主鍵,再添加外鍵。順序不能反了。
ALTER TABLE sj ADD CONSTRAINT sj_pk PRIMARY KEY(studid,jectid);
ALTER TABLE sj ADD CONSTRAINT sj_fk1 FOREIGN KEY(studid) REFERENCES stud(id);
ALTER TABLE sj ADD CONSTRAINT sj_fk2 FOREIGN KEY(jectid) REFERENCES ject(id);

//刪除外鍵約束
//ALTER TABLE sj DROP FOREIGN KEY sj_fk1;
//ALTER TABLE sj DROP FOREIGN KEY sj_fk2;

   

 

   3,添加一些演示數據

//實體表1
INSERT INTO stud VALUES('S001','Jack');
INSERT INTO stud VALUES('S002','Rose');
INSERT INTO stud VALUES('S003','Tom');

//實體表2
INSERT INTO ject VALUES('J001','Java');
INSERT INTO ject VALUES('J002','Oracle');
INSERT INTO ject VALUES('J003','XML');
INSERT INTO ject VALUES('J004','JSP');
INSERT INTO ject VALUES('J005','Game');

//關系表
INSERT INTO sj VALUES('S001','J001');
INSERT INTO sj VALUES('S001','J003');
INSERT INTO sj VALUES('S001','J004');
INSERT INTO sj VALUES('S002','J002');
INSERT INTO sj VALUES('S002','J003');
INSERT INTO sj VALUES('S002','J004');

   查詢那些人選了那些課

  SQL組織的1992標准,可用,但效率不高

mysql> SELECT stud.name, ject.NAME FROM stud,ject,sj WHERE stud.id=sj.studid AND ject.id=sj.jectid;
+------+--------+
| name | NAME   |
+------+--------+
| Jack | Java   |
| Jack | XML    |
| Jack | JSP    |
| Rose | Oracle |
| Rose | XML    |
| Rose | JSP    |
+------+--------+
6 rows in set (0.00 sec)

   //SQL組織的1996標准,效率高,推薦使用---關聯

mysql> SELECT stud.name, ject.NAME FROM stud INNER JOIN sj ON stud.id=sj.studid                                       INNER JOIN ject ON ject.id=sj.jectid;
+------+--------+
| name | NAME   |
+------+--------+
| Jack | Java   |
| Jack | XML    |
| Jack | JSP    |
| Rose | Oracle |
| Rose | XML    |
| Rose | JSP    |
+------+--------+
6 rows in set (0.00 sec)

   查詢那些人沒有選課

  首先使左連接查詢學生表和關系表對應表

mysql> select * from stud left join sj on stud.id=sj.studid;
+------+------+--------+--------+
| id   | name | studid | jectid |
+------+------+--------+--------+
| S001 | Jack | S001   | J001   |
| S001 | Jack | S001   | J003   |
| S001 | Jack | S001   | J004   |
| S002 | Rose | S002   | J002   |
| S002 | Rose | S002   | J003   |
| S002 | Rose | S002   | J004   |
| S003 | Tom  | NULL   | NULL   |
+------+------+--------+--------+
7 rows in set (0.00 sec)

   當學生表對應的關系表stuid或者jectid為空則代表該學生未選擇任何課程

  即可知道學生Tom未選擇任何課程

mysql> select * from stud left join sj on stud.id=sj.studid where sj.studid is NULL;
+------+------+--------+--------+
| id   | name | studid | jectid |
+------+------+--------+--------+
| S003 | Tom  | NULL   | NULL   |
+------+------+--------+--------+
1 row in set (0.00 sec)

   同理,查詢那些課程沒有人選

mysql> select * from ject left join sj on ject.id=sj.jectid where sj.studid is null;
+------+------+--------+--------+
| id   | name | studid | jectid |
+------+------+--------+--------+
| J005 | Game | NULL   | NULL   |
+------+------+--------+--------+
1 row in set (0.00 sec)

 



 

 

   

 

 

  


免責聲明!

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



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