1 外键

  • 外键:foreign key,外面的键(键不在自己表中),如果一张表中有一个字段(非主键)指向另外一张表的主键,那么将该字段称为外键。

1.1 增加外键

  • 外键可以在创建表的时候或创建表之后增加(但是要考虑数据的问题)。
  • 方案一:在创建表的时候增加外键,在所有的表字段之后,使用foreign key(外键字段) references 外部表 (主键字段);
-- 创建班级
CREATE TABLE my_class(
    id INT PRIMARY KEY AUTO_INCREMENT,
    c_name ) NOT NULL,
    room )
);
-- 创建学生表
CREATE TABLE my_student1(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME ) NOT NULL,
    c_id INT ,
    CONSTRAINT fk_c_id FOREIGN KEY (c_id) REFERENCES my_class (id)
);

  • 方案二:在新增表之后,增加外键,所以需要修改表结构。
alter table 表名 add [constraint 外键名字] foreign key (外键字段) references 父表(主键字段);
-- 创建班级
CREATE TABLE my_class(
    id INT PRIMARY KEY AUTO_INCREMENT,
    c_name ) NOT NULL,
    room )
);
-- 创建学生表
CREATE TABLE my_student2(
    id INT PRIMARY KEY AUTO_INCREMENT,
    NAME ) NOT NULL,
    c_id INT
);
ALTER TABLE my_student2 ADD CONSTRAINT fk_c_id FOREIGN KEY (c_id) REFERENCES my_class (id);

1.2 修改外键&删除外键

  • 外键不可以修改:只能先删除后新增。
alter table 表名 drop foreign key 外键名;--一张表中可以有多个外键,但是名字不能相同
ALTER TABLE my_student2 DROP FOREIGN KEY fk_c_id;

1.3 外键作用

  • 外键默认的作用有两点:

    • 一个对父表:父表数据进行写操作(删和改,都必须设计到主键本身),如果对应的主键在字表中已经被数据所引用,那么就不允许操作。
    • 一个对字表(外键字段所在的表):字表数据进行写操作(增和改)的时候,如果对应的外键字段在父表找不到对应的匹配,操作会失败。  

1.4 外键条件

  • 外键要存在:首先必须表的存储引擎是innodb。如果不是innodb存储引擎,那么外键可以创建成功,但是没有约束效果。
  • 外键字段的字段类型(列类型)必须和父表的主键类型完全一致。
  • 一张表中的外键名字不能重复。
  • 增加外键的字段(数据已经存在),必须保证数据和父表主键要求对应。

1.5 外键约束

  • 外键约束:就是外键的作用。
  • 外键约束有三种约束模式:都是针对父表的约束

    • district:严格模式(默认的),父表不能删除或更新一个已经被子表数据引用的记录(主键)。
    • cascade:级联模式,父表的操作,对应子表关联的数据也随之变化。
    • set null:置空模式,父表的操作之后,子表对应的数据(外键)被置空。  
  • 通常:父表删除的时候,子表置空;更新的时候,子表级联操作。
constraint 外键名字 foreign key (外键字段) references 主表(主键) on delete set null;
constraint 外键名字 foreign key (外键字段) references 主表(主键) on update cascade;
constraint 外键名字 foreign key (外键字段) references 主表(主键) on delete set null on update cascade;
  • 删除置空的前提:外键字段为空(如果不满足条件,外键无法创建)。
  • 外键虽然很强大,能够进行各种约束,但是对于java来说,外键约束降低了java对数据的可控性。所以,通常情况下,在实际开发中,很少使用外键的级联模式和置空模式。

2 联合查询

  • 联合查询:将多次查询语句,在记录上进行拼接。
  • 基本语法
多条select语句构成:每一条select语句获取的字段必须严格一致(但是字段类型无关)
select 语句1 union [union 选项] 语句2……;
-- union选项:与select选项一样有两个
-- all 保留所有(不管重复)
-- distinct 去重(整个重复):默认的
  • 示例:联合查询
SELECT * FROM my_class
UNION
SELECT * FROM my_class;

  • 示例:联合查询
SELECT id,c_name,room FROM my_class
UNION
SELECT id,c_id,NAME FROM my_student2;

  • 联合查询的意义

    • 查询同一张表,但是需求不同:如查询学生信息,男生身高升序,女生身高降序(面试题)。
    • 多表查询:多张表的结构是完全一样的,保存的数据(结构)也是一样的。  
  • 联合查询Order by使用

    • 在联合查询中:order by不能直接使用,需要对查询语句使用括号才行。  
(SELECT * FROM my_student2 WHERE sex = '男' ORDER BY height ASC)
UNION
(SELECT * FROM my_student2 WHERE sex = '女' ORDER BY height DESC);

    • 如果想order by生效:必须搭配limit,limit使用限定的最大数即可。  
()
UNION
();

3 子查询

  • 子查询:查询是在某个查询结果之上进行的(一条select语句内部包含了另外一条select语句)。
  • 子查询分类方式:

    • 按位置分类:子查询(select语句)在外部查询(select语句)中出现的位置。

      • From子查询:子查询在From之后
      • where子查询:子查询出现在where条件中
      • exists子查询:子查询出现在exists里面
    • 按照结果分类:根据子查询得到的数据进行分类(理论上任何一个查询得到的结果都可以理解为二维表)
      • 标量子查询:子查询得到的结果是一行一列。(出现在where之后)
      • 列子查询:子查询得到的结果是一列多行。(出现在where之后)
      • 行子查询:子查询得到的结果是多列一行(多行多列)(出现在where之后)
      • 表子查询:子查询得到的结果是多行多列(出现的位置在From之后)        
  • 示例脚本
-- 创建班级表
CREATE TABLE my_class(
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    c_name ) NOT NULL COMMENT '班级名字',
    room ) NOT NULL COMMENT '班级所在教室'
);
-- 插入班级信息
INSERT INTO my_class VALUES (NULL,'java001班','A01');
INSERT INTO my_class VALUES (NULL,'Linux003班','C15');
INSERT INTO my_class VALUES (NULL,'c005班','B23');

-- 创建学生表
CREATE TABLE my_student(
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
    NAME ) NOT NULL COMMENT '学生姓名',
    age INT NOT NULL COMMENT '学生年龄',
    gender ) NOT NULL COMMENT '学生性别',
    c_id INT COMMENT '外键' ,
    CONSTRAINT fk_c_id FOREIGN KEY (c_id) REFERENCES my_class (id)
);
-- 插入学生信息
,);
,);
,);
,);
,);
,);

3.1 标量子查询

  • 示例:查询java001班的所有学生。

    • ①确定数据源:获取所有的学生
select * from my_student where c_id = ?;
    • ②获取班级id:可以通过名字确定。  
SELECT id FROM my_class WHERE c_name = 'java001班' ; -- 一行一列
    • ③最后的执行SQL语句  
SELECT * FROM my_student WHERE c_id = (SELECT id FROM my_class WHERE c_name = 'java001班' );

3.2 列子查询

  • 示例:查询所有在读班级的学生(班级表中存在的班级)  

    • ①确定数据源:学生   
SELECT *FROM my_student WHERE c_id IN (?);
    • ②确定有效班级的id:所有班级的id  
SELECT id FROM my_class
    • 最后的执行SQL语句  
SELECT *FROM my_student WHERE c_id IN (SELECT id FROM my_class);

  • 列子查询返回的结果会比较:一列多行,需要使用in作为条件匹配:其实在mysql中还有几个类似的条件:all、some、any。

3.3 行子查询

  • 行子查询:返回的结果可以是多行多列(一行多列)
  • 修改学生表
ALTER TABLE my_student ADD height INT NOT NULL COMMENT '身高';
 ;
 ;
 ;
 ;
 ;
 ;
  • 示例:要求查询整个学生中,年龄最大且身高

    • 思路1:  

      • ①确定数据源    
select * from my_student where age = ? and height = ?;
      • ②确定最大的年龄和最高的身高    
select max(age),max(height) from my_student;
      • ③最后的SQL执行语句    
SELECT * FROM my_student WHERE (age = (SELECT MAX(age) FROM my_student)) AND  (height =  (SELECT MAX(height) FROM my_student));

      • ④貌似上面的是对的哦,但是如果最高的年龄最大,身高最高的不是一个人呢?这样就不能查到数据呢,所以,综上所述,上面的思路貌似正确,但是不合题意。    
    • 思路2:正确解法
      • 需要构造行元素:行元素是由多个字段构成。     
SELECT * FROM my_student WHERE (age,height) = (SELECT MAX(age),MAX(height) FROM my_student);

3.4 表子查询

  • 表子查询:子查询返回的结果是当做二维表来使用。
  • 示例:找出每个班中最高的一个学生。

    • ①先对学生按照身高降序  
SELECT * FROM my_student  ORDER BY height DESC
    • ②对排序后的学生临时表按照班级分组  
SELECT * FROM (SELECT * FROM my_student  ORDER BY height DESC) AS student GROUP BY student.c_id;
    • 当然,这一题可能有人会这样想?我先对学生分组,求出最大的年龄,然后用in子句,就可以了。  
SELECT * FROM my_student WHERE height IN (SELECT MAX(height) FROM my_student GROUP BY c_id);
    • 当然,第二种思路也是可以的。      

3.5 exists子查询

  • exists:是否存在,exists子查询是用来判断某些条件是否满足(跨表),exists是在where之后,exists返回的结果是0或1。
  • 示例:查询所有的学生,前提条件是班级存在。

    • ①确定数据源  
SELECT * FROM my_student WHERE ?;
    • ②确定条件是否满足  
EXISTS(SELECT * FROM my_class)
    • 最后的执行SQL语句    
SELECT * FROM my_student WHERE EXISTS(SELECT * FROM my_class);

MySQL (六)--外键、联合查询、子查询的更多相关文章

  1. MySQL数据库(4)_MySQL数据库外键约束、表查询

    一.外键约束 创建外键 --- 每一个班主任会对应多个学生 , 而每个学生只能对应一个班主任 ----主表 CREATE TABLE ClassCharger( id TINYINT PRIMARY ...

  2. MySQL的查询,子查询,联结查询,联合查询

    MySQL的查询,子查询,联结查询,联合查询 一.mysql查询的五种子句where(条件查询).having(筛选).group by(分组).order by(排序).limit(限制结果数) 二 ...

  3. MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作)

    MySQL的外键,修改表,基本数据类型,表级别操作,其他(条件,通配符,分页,排序,分组,联合,连表操作): a.创建2张表 create table userinfo(nid int not nul ...

  4. MYSQL 查询方法 统计查询 链接查询 子查询

    mysql表格查询方法: 查询: 1.简单查询 select * from Info --查所有数据select Code,Name from Info --查指定列的数据select Code as ...

  5. 吃货眼中的sqlalchemy外键和连表查询

    前言 使用数据库一个高效的操作是连表查询,一条查询语句能够查询到多个表的数据.在sqlalchem架构下的数据库连表查询更是十分方便.那么如何连表查询?以及数据库外键对连表查询有没有帮助呢?本篇文章就 ...

  6. MySQL(18):Select- subquery子查询

    1. Select- subquery子查询 子查询:是将一条查询语句嵌套在另一条查询语句之中. 2. 案例 需求:查询获得代课天数最多的那个老师的信息. 思路:先获得最多的代课天数是多少天,然后再判 ...

  7. MySQL数据库--外键约束及外键使用

    什么是主键.外键关系型数据库中的一条记录中有若干个属性,若其中某一个属性组(注意是组)能唯一标识一条记录,该属性组就可以成为一个主键. 比如: 学生表(学号,姓名,性别,班级) 其中每个学生的学号是唯 ...

  8. Python-select 关键字 多表查询 子查询

    sql 最核心的查询语句!!!! 增删改 单表查询 select语句的完整写法 关键字的书写顺序 执行顺序 多表查询 笛卡尔积 内连接 左外连接 右外连接 全外连接 通过合并左外连接和右外连接 子查询 ...

  9. 第二百八十节,MySQL数据库-外键链表之一对多,多对多

    MySQL数据库-外键链表之一对多,多对多 外键链表之一对多 外键链表:就是a表通过外键连接b表的主键,建立链表关系,需要注意的是a表外键字段类型,必须与要关联的b表的主键字段类型一致,否则无法创建索 ...

  10. 【知识库】-数据库_MySQL之基本数据查询:子查询、分组查询、模糊查询

    简书作者:seay 文章出处: 关系数据库SQL之基本数据查询:子查询.分组查询.模糊查询 回顾:[知识库]-数据库_MySQL常用SQL语句语法大全示例 Learn [已经过测试校验] 一.简单查询 ...

随机推荐

  1. js单页hash路由原理与应用实战

    什么是路由? 通俗点说,就是不同的URL显示不同的内容 什么是单页应用? 单页,英文缩写为SPA( Single Page Application),就是把各种功能坐在一个页面内. 那所谓的单页路由应 ...

  2. 在Entity Framework 中用 Code First 创建新的数据库

    在Entity Framework 中用 Code First 创建新的数据库 (原文链接) 本文将逐步介绍怎样用Code First 创建新数据库,使用在代码中定义类和API中提供的特性(Attri ...

  3. StringBulider简单用法

    StringBuild的是个动态对象,可直接拼加上字符串:而string对象的步骤:先初始化对象并赋值了,而后在拼加字符串时,先要创建需要拼加的字符串,然后再拼加,所以这就是StirngBuild远比 ...

  4. android炫酷动画源码,QQ菜单、瀑布流、二维码源码

    Android精选源码 自定义弹框封装,ProgressDialog,StatusDialog和Toast,支持自定义颜色 有深度感的fragment代码 在屏幕顶部或者底部显示提示 短信转发工具,自 ...

  5. IE10 特有 MSGesture() 方法

    gesturechange方法 是 ie10以上特有的方法. 初始化:oMsg = new MSGesture(); 主要功能和方法: 用于IE下浏览器的DOM元素触发事件 包括 : MSGestur ...

  6. Win7系统默认的壁纸路径

    Win7系统默认的壁纸路径.. ------------------- ------------------- ------------------- ------------------- ---- ...

  7. 【整合】input标签JS改变Value事件处理方法

    某人需要在时间控件给文本框赋值时,触发事件函数.实现的效果: 1.文本框支持手工输入,通过用户输入修改值,手工输入结束后触发事件.阻塞在于失去焦点后才触发(输入过程中不触发事件) 2.通过JS方法修改 ...

  8. js实现每次程序发送一个数据 ,多次发送不一样,5秒后继续执行多次程序,判断如果五秒后发送过来的数据和上次不一样,少的删除多的增加

    /*存储设备ID*/var IDSNew = new Array();//判断是否已经启用服务var isopen = true;//需要放到接收设备数据处IDSNew[client.deviceId ...

  9. Jmeter之接口测试

    最近才入职新公司,好几天没有写博客了,经过一个朋友提醒,刚刚好觉得用Jmeter来做接口测试真的是再好不过了.下面就详细讲解下这两天我利用Jmeter做的接口测试. [安装Jmeter] 详细见博文: ...

  10. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...