MySQL基础2(外键约束详细讲述、DML(添加、修改、删除)、DQL查询语言(去重、WHERE、联表查询(JOIN)、自连接、排序分页、子查询、过滤分组))

MySQL基础

MySQL数据管理

外键约束
  1. 什么是外键?
    外键是相对于主键说的,是建立表之间的联系的必须的前提,比如有两张表,student(学生)表和grade(年级)表,student 中 id 是主键,而 gradeid 是依赖于 student 中的 id ,那么 grade 中的 id 就是 student 的外键;我们可以通过外键使两张表进行关联。
  2. 外键的作用是什么?
    使两张表形成关联,外键只能引用外表中的列的值,可以使得两张表关联,保证数据的一致性和实现一些级联操作。
    总结:
    1)为了一张表记录的数据不要太过冗余;
    2)保持数据的一致性、完整性。
  • CREATE TABLE 时:
-- 创建grade表
CREATE TABLE `grade`(  
`gradeid` INT(10) NOT NULL AUTO_INCREMENT COMMENT '年级id',  
`gradename` VARCHAR(50) NOT NULL COMMENT '年级名称',  
PRIMARY KEY (`gradeid`) 
)ENGINE=INNODB DEFAULT CHARSET=utf8

-- 学生表的 gradeid 字段,去引用年级表的 gradeid 
-- 定义外键key 
-- 给这个外键添加约束 (执行引用)  references 引用
CREATE TABLE IF NOT EXISTS `student` (   
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',   
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',   
`pwd` VARCHAR(20)NOT NULL DEFAULT '123456' COMMENT '密码',   
`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',   
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',   
`gradeid` INT(10) NOT NULL COMMENT '学生的年级',   
`address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',   
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',   
PRIMARY KEY(`id`),   
KEY `FK_gradeid` (`gradeid`),   
CONSTRAINT `FK_gradeid` FOREIGN KEY (`gradeid`) REFERENCES `grade`(`gradeid`) 
)ENGINE=INNODB DEFAULT CHARSET=utf8

可视化查看表可以看到:
在这里插入图片描述

  • ALTER TABLE 时:
-- 当我们的student表已经存在时,添加外键约束
CREATE TABLE IF NOT EXISTS `student` (   
`id` INT(4) NOT NULL AUTO_INCREMENT COMMENT '学号',   
`name` VARCHAR(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',   
`pwd` VARCHAR(20)NOT NULL DEFAULT '123456' COMMENT '密码',   
`sex` VARCHAR(2) NOT NULL DEFAULT '女' COMMENT '性别',   
`birthday` DATETIME DEFAULT NULL COMMENT '出生日期',
`gradeid` INT(10) NOT NULL COMMENT '学生的年级',   
`address` VARCHAR(100) DEFAULT NULL COMMENT '家庭住址',   
`email` VARCHAR(50) DEFAULT NULL COMMENT '邮箱',   
PRIMARY KEY(`id`) 
)ENGINE=INNODB DEFAULT CHARSET=utf8
-- ALTER TABLE 表 
-- ADD CONSTRAINT 约束名 FOREIGN KEY(作为外键的列) REFERENCES 哪个表(哪个字段)
ALTER TABLE `student` 
ADD CONSTRAINT `FK_gradeid` FOREIGN KEY(`gradeid`) REFERENCES `grade`(`gradeid`);

和上面结果一样。

  • 注意:
    加入外键约束后,没删除student表前,是无法删除grade表的;
    一般也不推荐使用外键约束,阿里巴巴的Java规范下是:强制不得使用外键,一切外键在应用层解决,原因就是在DELETE或者UPDATE时都要考虑外键约束,导致开发变得痛苦很多!
DML语言

DML:数据操纵语言(Data Manipulation Language),它可以实现对数据库的基本操作。

开始我们创建一个school数据库,里面包含了以下的表,接下来的操作都是在此数据库里进行的
在这里插入图片描述

  1. 添加(INSERT)
    语法:INSERT INTO 表名([字段名1,字段2,字段3,...]) VALUES ('值1'),('值2'),('值3',....)
-- 给上面的student表插入数据
INSERT INTO `student`(`name`) VALUES ('张三')
INSERT INTO `studnet` VALUES('李四') -- 如果不写表的字段,他就会一一匹配,这条语句就会报错!
-- 插入多个字段 
INSERT INTO `student`(`name`,`pwd`,`sex`) VALUES ('张三','123456','男')
INSERT INTO `student`(`name`,`pwd`,`sex`) VALUES ('李四','123456','男'),('王五','aaaaaa','男')
  • 注意:
    1)字段和字段之间使用英文逗号隔开;
    2)字段是可以省略的,但是后面的值必须要要一一对应,不能缺少数据;
    3)可以同时插入多条数据,VALUES 后面的值,需要使用逗号隔开。
  1. 修改(UPDATE)
    语法:UPDATE 表名 SET colnum_name = value,[colnum_name = value,....] WHERE [条 件]
-- 修改student表name字段
UPDATE `student` SET `name`='小明' WHERE id = 1;
-- 不指定条件的情况下,会改动所有表 
UPDATE `student` SET `name`='小红';
-- 修改多个属性,逗号隔开 
UPDATE `student` SET `name`='小强',`email`='123456@qq.com' WHERE id = 1;
  • 注意:
    1)WHERE 条件子句 :id 等于某个值,或大于某个值,表示在某个区间内修改;
    2)colnum_name 是数据库的列,尽量带上`` ;
    3)条件,筛选的条件,如果没有指定,则会修改所有的列;
    4)value,是一个具体的值,也可以是一个变量;
    5)多个设置的属性之间,使用英文逗号隔开。

通过多个条件定位数据

UPDATE `student` SET `name`='小强' WHERE `name`='张三' AND sex='男'
  1. 删除(DELETE)
    语法:DELETE FROM 表名 [WHERE 条件]
-- 删除数据 (这样写,会全部删除) 
DELETE FROM `student`;
-- 删除指定数据 
DELETE FROM `student` WHERE id = 1;

完全清空一个数据库表(TRUNCATE)

--清空 student 表 
TRUNCATE `student`;

DELETE 和 TRUNCATE:
相同点:都能删除数据,都不会删除表结构
不同点: DELETE ,不会影响自增;TRUNCATE ,重新设置自增列,计数器会归零 。

DQL语言

DQL:数据查询语言(Data Query Language,所有的查询操作都用它,数据库中最核心的语言,最重要的语句,使用频率最高的语句。

  1. 指定查询字段
-- 查询全部的学生  SELECT 字段 FROM 表 
SELECT * FROM student
-- 查询指定字段 
SELECT `StudentNo`,`StudentName` FROM student
-- 给查询结果赋值一个新的名字  AS  可以给字段起别名,也可以给表起别名 
SELECT `StudentNo` AS 学号,`StudentName` AS 学生姓名 FROM student AS s
-- 函数  Concat(a,b),给查询结果拼接一个字符串 
SELECT CONCAT('姓名:',StudentName) AS 新名字 FROM student

有的时候,列名字不是那么的见名知意,所以我们赋值一个新的名字,语法:字段名 AS 别名 表名 AS 别名

  1. 去重 (DISTINCT)
    去除SELECT 查询出来的结果中重复的数据,重复的数据只显示一条
SELECT DISTINCT `StudentNo` FROM result 
  1. 数据库的列(表达式)
-- 查询系统版本 (函数)
SELECT VERSION()  
-- 用来计算  (表达式) 
SELECT 100*3-1 AS 计算的结果为  
-- 查询自增的步长  (变量)
SELECT @@auto_increment_increment 
-- 给student表的考试成绩都 + 1分 
SELECT `StudentNo`,`StudentResult`+1 AS '提分后' FROM result
  1. WHERE条件子句
    用来检索数据中 符合条件 的值
    MySQL官网的函数和运算符说明:点击这里

简单说几个:

符号描述语法
<> 或 !=不等于id <> 3、id != 3
BETWEEN … and …在某个范围内
AND、&&逻辑与a and b 、 a&&b
OR逻辑或a or b
Not !逻辑非not a !a
IS NULL如果操作符为 NUll, 结果为真a is null
IS NOT NULL如果操作符不为 null,结果为真a is not null
BETWEEN若a 在 b 和c 之间,则结果为真a between b and c
LIKESQL 匹配,如果a匹配b,则结果为真a like b
Ina在a1,或者a2…. 其中的某一个值中,结果为真a in (a1,a2,a3….)
-- 查询考试成绩在 95~100 分之间 
SELECT studentNo,`StudentResult` FROM result 
WHERE StudentResult>=95 AND StudentResult<=100
-- 模糊查询(区间) 
SELECT studentNo,`StudentResult` FROM result 
WHERE StudentResult BETWEEN 95 AND 100
-- 查询学号不为1000的学生成绩 
SELECT studentNo,`StudentResult` FROM result 
WHERE studentNo!=1000;
SELECT studentNo,`StudentResult` FROM result 
WHERE NOT studentNo = 1000

模糊查询:

-- 查询姓张的同学 
SELECT `StudentNo`,`StudentName` FROM `student`
WHERE StudentName LIKE '张%' -- %(代表0到任意个字符)    
-- 查询姓刘的同学,而且名字后面只有一个字的 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE StudentName LIKE '刘_' -- _(代表一个字符)
-- 查询姓刘的同学,名字后面只有两个字的 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE StudentName LIKE '刘__'
-- 查询名字中间有坤字的同学 %坤% 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE StudentName LIKE '%坤%'
-- 查询 1001,1002,1003号学生
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE StudentNo IN (1001,1002,1003);
-- 查询地址为北京的学生 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE `Address` IN ('北京');
-- 查询地址为空的学生 null  '' 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE address=''  OR address IS NULL
-- 查询有出生日期的同学,不为空 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE `BornDate` IS NOT NULL
-- 查询没有登记出生日期的同学,为空 
SELECT `StudentNo`,`StudentName` FROM `student` 
WHERE `BornDate` IS NULL
  • 注意:
    WHERE IN()查询时,IN()里面是具体的值,如果地址是北京市海淀区,当你输入WHERE Address IN ('北京'),结果是查询不到的,只能采用WHERE Address LIKE '%北京%'
  1. 联表查询(JOIN)
    LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN 相关的 7 种用法
    在这里插入图片描述
  • 思路:
    1)分析需求,分析查询的字段来自哪些表?并进行连接查询;
    2)确定使用上图的哪种连接查询?
    3)确定交叉点(这两个表中哪个数据是相同的;
    4)判断的条件
-- INNER JOIN
SELECT s.studentNO,studentName,SubjectNo,StudentResult 
FROM student AS s 
INNER JOIN result AS r 
ON s.studentNO = r.studentNO
-- Right JOIN 
SELECT s.studentNO,studentName,SubjectNo,StudentResult 
FROM student s 
RIGHT JOIN result r 
ON s.studentNO = r.studentNO
-- Left JOIN
SELECT s.studentNO,studentName,SubjectNo,StudentResult 
FROM student s 
LEFT JOIN result r 
ON s.studentNO = r.studentNO
  • 注意:
JOIN描述
INNER JOIN如果表中有至少一个匹配,则返回行
LEFT JOIN即使右表中没有匹配,也从左表返回所有的行
RIGHT JOIN即使左表中没有匹配,也从右表返回所有的行
  • 总结:
    联表查询思路:
    1)首先确定要查询哪些数据:SELECT ...
    2)从哪几个表中查 FROM 表 XXX JOIN 连接的表 on 交叉条件
    3)假设存在一种多张表查询,先查询两张表,然后再慢慢增加。
  1. 自连接
    自己的表和自己的表连接,将一张表拆为两张一样的表即可

假设一张表:

categoryidpidcategoryName
21水果
31蔬菜
43土豆
51肉类
63青菜
75猪肉
82西瓜

拆分这张表:
表1:

categoryidcategoryName
2水果
3蔬菜
5肉类

表二:

pidcategoryidcategoryName
34土豆
28西瓜
36青菜
57猪肉

操作:查询父类对应的子类关系

父类子类
水果西瓜
蔬菜土豆、青菜
肉类猪肉
-- 通过别名将一张表看作两个一摸一样的表
SELECT a.`categoryName` AS '父栏目',b.`categoryName` AS '子栏目' 
FROM `category` AS a,`category` AS b
WHERE a.`categoryid` = b.`pid`
  1. 排序和分页
  • 排序(ORDER BY)
-- 升序 ASC , 降序DESC 
ORDER BY StudentResult ASCDESC 
  • 分页(LIMIT)
    缓解数据库压力,给人的体验更好
    语法: LIMIT (查询起始下标,pageSize)
第一页  LIMIT 0,5      (1-1)*5 
第二页  LIMIT 5,5      (2-1)*5 
第三页  LIMIT 10,5     (3-1)*5 
第N页   LIMIT 0,5      (n-1)* pageSize,pageSize 
pageSize:页面大小
(n-1)* pageSize:起始值
n :当前页 
数据总数/页面大小 = 总页数
  1. 子查询
    在where语句中嵌套一个子查询语句,查询高数考试学生的成绩、学号,成绩降序排序
-- 方式一: 使用连接查询 
SELECT `StudentNo`,r.`SubjectNo`,`StudentResult` 
FROM `result` r 
INNER JOIN `subject` sub 
ON r.SubjectNo = sub.SubjectNo 
WHERE SubjectName = '高数' 
ORDER BY StudentResult DESC

-- 方式二: 使用子查询(由里及外) -- 查询所有数据库结构-1 的学生学号 
SELECT `StudentNo`,`SubjectNo`,`StudentResult` 
FROM `result` WHERE SubjectNo = (      
SELECT SubjectNo FROM `subject`       
WHERE SubjectName = '高数' 
) ORDER BY StudentResult DESC
  1. 过滤分组
-- 通过什么字段来分组
GROUP BY xxx  
-- 过滤分组后的信息,需要满足的条件,次要条件
HAVING xxx

//下篇再见…谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值