參考: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)