mysql之外连接的用法

时间:2021-05-24 00:47:09
       现在假设有两个表,分别为a表和b表,a表与b表外键关联,如果我们想要查询a表和b表中的一些记录,我们就需要通过a表的外键和b表的主键进行连接。
       但是假设如下情况。 b表有主键bno,数据为b1,b2,b3 a表中有外键bno,但是只有关于b1,b2的数据,没有关于b3的数据(这里只考虑bno,其他属性类似bname等可不考虑),如果我们进行等值连接的话,连接后关于b3的数据必然会丢失,假如我们想查询bno值为b3的信息的话,是肯定查询不到的,因为已经丢失了。
       从这里我们也可以看出等值连接的特点。如果主外键匹配,连接成功,数据可以显示。如果主外键不匹配(或者无法匹配,如上面的情况),连接失败,该数据丢失。
       如果我们想要查询出某些等值连接会丢失的数据,应该怎么做呢,这时候就要用外连接了。

      外连接有左外连接、右外连接和全外连接,这里逐一介绍。

先给出创建表的语句和插入数据的语句:

创建表的语句:

CREATE TABLE `csdn`.`b` (
  `bno` CHAR(5) NOT NULL,
  PRIMARY KEY (`bno`));


CREATE TABLE `csdn`.`a` (
  `ano` CHAR(5) NOT NULL,
  `bno` CHAR(5) NULL,
  PRIMARY KEY (`ano`),
  CONSTRAINT `FK_a_b`
    FOREIGN KEY (bno)
    REFERENCES `csdn`.`b` (bno)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION);

这里我的数据库名为csdn,如果不同的话改成自己正在使用的数据库即可。(或者创建一个新数据库更方便点)创建表的顺序应该是先b后a,因为a与b外键关联。

插入数据的语句:

INSERT INTO `csdn`.`b` (`bno`) VALUES ('b1');
INSERT INTO `csdn`.`b` (`bno`) VALUES ('b2');
INSERT INTO `csdn`.`b` (`bno`) VALUES ('b3');

INSERT INTO `csdn`.`a` (`ano`, `bno`) VALUES ('a1', 'b1');
INSERT INTO `csdn`.`a` (`ano`, `bno`) VALUES ('a2', 'b2');


  1.左外连接
     左外连接(LEFT JOIN)是指将左表中的所有数据分别与右表中的每条数据进行连接组合,返回的除内连接外,还包括左表中不符合条件的数据,并在右表的相应列中添加NULL值。
     简单点来说,就是可以等值连接的就等值连接,不能的左表数据保留,右表数据全部用NULL填上。
     那上面的假设就可以这样写出。

   
select  * from b left join a on a.bno=b.bno
where a.bno IS NULL;



mysql之外连接的用法




2.右外连接
       右外连接(RIGHT JOIN)是指右表中的所有数据分别与左表中的每条数据进行连接组合,返回的结构除内连接数据外,还包括右表中不复合条件的数据,并在左表的相应列中添加NULL。
和左外连接是类似的。只是数据部分和NULL部分左右互换而已。

select * from a right join b on a.bno=b.bno;

mysql之外连接的用法

但是这里要搞清楚的是到底是哪个表的数据会被丢失,例如上面的例子中,我们知道进行等值连接的话是b表的信息会被丢失,所以b表就不能放在会被赋值NULL的位置,不然的话效果等同等值连接。

select * from b right join a on a.bno=b.bno;
select * from a left join b on a.bno=b.bno;
select * from a,b where b.bno=a.bno;
这三条语句执行后结果只有两行。(这里才知道原来连接时属性的顺序是按照你的输入的表的顺序来的。。)

3.全外连接
全外连接(FULL  JOIN 或 FULL OUTER JOIN) 完整外部连接返回左表和右表中的所有行。当某行在另一个表中没有匹配行时,则另一个表的选择列表列包含空值。如果表之间有匹配行,则整个结果集行包含基表的数据值。  

但是在mysql中,并不支持全外连接。所以这里不再给出查询语句和结果。


总结:如果要确保在连接的过程中数据不会丢失,我们就需要使用外连接,但是我们也需要知道哪个表的信息是将会被丢失的。这里有个简单点的方法,就是左外和右外各写一句。但是表的位置要相同(均为b在前或者均为a在前,如下),这样观察一下两表的不同就知道了。

select * from b left join a on a.bno=b.bno;
select * from b right join a on a.bno=b.bno;