Mysql
Posted tacit-lxs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql相关的知识,希望对你有一定的参考价值。
mysql(三)
mysql数据管理
1.外键
-- 学生表的gradeid想要引用年纪表的gradeid,就要定义外键key,创建外键约束,执行引用
-- 1.创建表的时候加外键约束
key 'FK_gradeid' ('gradeid'),
constraint 'FK_gradeid' foreign key ('gradeid') reference 'grade' ('gradeid')
-- 2.创建好表之后加外键约束:
-- alter table 表名 add constraint 约束名 foreign key(作为外键的列) reference 那个表(那个字段)
alter table student
add constraint 'FK_gradeid' foreign key('gradeid') reference 'grade'('gradeid')
以上均为物理外键,不建议使用,因为使用外键会导致在删除和更新是必须考虑外键约束。
- 数据库就是单纯的表,只用来存数据,只有行(数据)和列(字段)。
- 可以用程序实现操作多表数据,实现外键。
2. DML语言
2.1 添加(Insert)
**语法:**insert into 表名 ([字段名1,字段名2,字段名3])values (‘值1’,…) ,(‘值2’,…),(‘值3…’)
-- 插入数据,自增长的字段不用管
insert into grade ('gradename') values ('研一')
-- 插入多个字段
insert into grade ('gradename') values ('研一'),('研二')
-- 有多个字段名
insert into 'student' ('name','pwd','sex') values ('张三','3232','男')
-- 字段省略
insert into 'student' values(2,'李四','3233','男')
注意事项:
- 字段与字段之间使用英文隔开
- 字段名是可以省略的,但是后面的值必须要一一对应,不能少
- 可以同时插入多条语句,values后面的值,需要使用,隔开,即:(),()
2.2 修改(Update)
**语法:**update 表名 set column_name = value , [column_name = value,…] where [条件]
--修改属性
update 'student' set 'name' = '张三' where id = 1
-- 修改多个属性,逗号隔开
update 'student' set 'name' = '张三' , 'email' = '2534@qq.com' where id = 1
-- 通过多个条件定位数据
update 'student' set 'name' = '张三' where 'name' = '李四' and sex = '女'
条件:
操作符 | 含义 |
---|---|
> 、>=、<、<=、!=或<>、 | |
between … and … | 一个闭合区间 |
AND | 相当于&& |
OR | 相当于|| |
注意事项:
-
column_name 是数据库的列,尽量带上’ '。
-
筛选的条件如果不加上会改变所有的列。
-
value的值可以是具体的值,也可以是一个变量(一般指时间)。
update 'student' set 'birthday' = CURRENT_TIME where 'name' = '李四' and sex = '女'
2.3 删除(Delete)
**语法:**delete from 表名 where [条件]
delete from 'student' where id = 1
Truncate:完全清空数据表,表的结构和索引约束不会变
truncate table 'student'
-- 与delete的区别
-- turncate会影响自增而delete不会影响自增
-- truncate不会影响事物
拓展:
做delete删除,重启数据库的现象:
- InnoDB:自增列会重1开始(存在内存中,断电即失)
- MyISAM: 继续从上一个自增量开始(存在于文件中,不会丢失)
3. DQL(Data Query language)
-
它是数据库中最核心、最重要的语言
-
使用频率最高的语言
-
简单、复杂他都行(Select)
-
完整语法
select [ALL | Distinct] -- 去重 * | table.* | [table.field1[as 别名][,table.field2[as 别名]][......] -- 查询那个字段 from table_name [as 别名] [left | right | inner join table_name2 [on 条件]] --联合查询 [where ...] -- 指定结果需要满足的条件(具体的值 或 子查询语句) [Group by ...] -- 指定结果按照那几个字段来分组 [HAving] -- 过滤分组的记录必须满足的次要条件(相比于where可以是聚合函数) [Order by ...] -- 指定查询记录按一个或多个条件排序 [Limit [offset,]row_count | row_countOffset offset]; -- 指定查询的记录从那条至那条
- 在实际业务中,select并不是这么简单,在一个页面显示的画面,后面支撑的数据可能来自不同的表,甚至是不同的数据库,有时候还可能跨地区。
3.1 简单查询
**语法:**select 字段, … from 表名
-- 查询所有学生
select *from student
-- 查询指定字段
select 'studentNo','studentName' from student
-- 可以给字段和表起别名
select 'studentNo' as 学号,'studentName' as 学生姓名 from student as s
-- 函数 Concat(a,b):拼接
select Concat('姓名:',studentName) as 新名字 from student
去重 distinct
作用:去除select语句查询出来的数据,重复的数据只显示一行
select distinct 'studentNo' from result -- 查询哪些同学参加了考试
数据库中的列
select version() -- 查询版本号
select 100*3-5 -- 用来计算
select @@auto_increment_increment --查询自增的步长(变量)
--学员考试成绩加一
select 'studentNo','studentResult'+1 as '提分后' from result
数据库中的表达式:文本值,列,Null,函数,计算表达式,系统变量…
**语法升级:**select 表达式 from 表名
3.2 where条件语句
where条件语句
作用:检索数据中符合条件的值
搜索条件由一个或者多个表达式组成!结果布尔值
逻辑运算符
运算符 | 语法 | 描述 |
---|---|---|
and && | a and b a&&b | 逻辑与,两个都为真,结果为真 |
or || | a or b a||b | 逻辑非,其中一个为真,结果为真 |
not ! | not a !a | 逻辑非,真为假,假为真 |
- 例子
-- 查询分数在90到100的学生学号
select studentNo from result where studentScore >= 90 and studentScore <= 100
select studentNo from result where studentScore >= 90 && studentScore <= 100
select studentNo from result where studentScore between 90 and 100 -- 模糊查询区间
-- 除了学号为1000的学生的成绩
select studentNo,studentScore from result where not studentNo = 1000
select studentNo,studentScore from result where studentNo != 1000
3.3 模糊查询
运算符 | 语法 | 描述 |
---|---|---|
is Null | a is null | 操作符为null,结果为真 |
is not Null | a is not null | 操作符不为null,结果为真 |
between | a between b and c | 若a在b和c之间,则结果为真 |
like | a like b | Sql匹配,如果a匹配b,则结果为真 |
in | a in (a1,a2,a3,…) | 假设a在a1,或a2,或a3…中,则结果为真 |
-
例子
-- like 结合 %(表示0到任意个字符) _(代表一个字符) select studentName from student where studentName like '廖%' -- 查询姓廖的同学 select studentName from student where studentName like '廖_' --查询姓廖且名字只有两个字的同学的姓名 select studentName from student where studentName like '%晓%' --查询名字中间有晓字得同学的姓名 -- In(具体的一个或多个值) --查询学号为1001,1002,1004的学生的信息 select studentNo, studentName from student where studentNo in(1001,1002,1004) -- 查询地址在重庆的学生信息 select studentNo,studentName from student where studentAddr in ('重庆') -- 查询地址为空的学生 select studentNo,studentName from student where studentAddr = '' or studentAddr is null
3.4 联表查询
--inner SELECT ename,jname FROM emp e inner JOIN job j ON e.job_id = j.id --(只要满足这个条件,就返回对应的行) --left SELECT ename,jname FROM emp e left JOIN job j ON e.job_id = j.id --(在inner的基础上,不管满不满足条件都会返回所有需要的左边表的信息) --right SELECT ename,jname FROM inneremp e RIGHT JOIN job j ON e.job_id = j.id --(在inner的基础上,不管满不满足条件都会返回所有需要的右边表的信息)
操作 描述 inner join 如果两表有满足条件的匹配,就返回行 left join 会从左表中返回所有的值,即使右表中没有匹配 right join 会从右表中返回所有的值,即使左表中没有匹配 例子:
-- 思路: -- 1.需求分析,分析要查询的字段来自那些表 -- 2.确定使用哪种连接,并确定连接点(表中那些表的数据是相同的)作为判断的条件。 -- join ... on (连接查询) -- where 等值查询 --查询学生学号、姓名、考试科目、成绩 select studentNo,studentName,subjectName,stuResult from student s left join result r on s.studentNo = r.studentNo inner join subject sub on r.subjectNo = sub.subjectNo
3.4 自连接
-
自己的表和自己的表连接,解决核心:把一张表看作两张一模一样的表。
如果一张表主副id,这样的表可以进行自连接
如下表:
categoryid pid categoryName 2 1 信息技术 3 1 软件开发 4 3 数据库 5 1 美术设计 6 3 web开发 7 5 ps技术 8 2 办公信息
进行拆分:
1为顶级id的生成一张主表
categoryid | categotyName |
---|---|
2 | 信息技术 |
3 | 软件开发 |
5 | 美术设计 |
在根据原表的pid匹配主表的categoryid生成子类
pid | categoryid | categotyName |
---|---|---|
3 | 4 | 数据库 |
3 | 6 | web开发 |
5 | 7 | ps技术 |
2 | 8 | 办公信息 |
select a.categoryName as 父类, b.categoryName as 子类
from category a ,category b
where a.categoryid = b.pid
-- 结果如下:
父类 | 子类 |
---|---|
软件开发 | 数据库 |
软件开发 | web开发 |
美术技术 | ps技术 |
信息技术 | 办公信息 |
3.5 分页和排序
--查询学生学号、姓名、考试科目、成绩,按成绩升序(ASC)排序\\降序(Desc)
select studentNo,studentName,subjectName,stuResult
from student s
left join result r
on s.studentNo = r.studentNo
inner join subject sub
on r.subjectNo = sub.subjectNo
where subjectName = '数据库原理'
order by stuResult Asc
Limit 5,5
-- 第二个5为pageSize:页面大小
-- 第一个5为起始页[(n-1)*pageSize]
-- n:当前页 这里当前页数为2
-- [数据总数/页面大小 = 总页数]
2.6 子查询和嵌套查询
where
其本质就是:在where语句里加循环语句。
嵌套查询就是查询语句里面再加入查询语句。
-- 查询成绩大于80并且该科目为数据库的学生的学号和姓名
select studentNo,studentName from student where studentNo in(
select studentNo from result where stuResult >= 80 And
subjectNo = (
select subjectNo from subject where subName = '数据库'
)
)
--普通查询
select s.studentNo,s.studentName from student s
inner join result r
on s.studentNo = r.studentNo
inner join subject sub
on r.subjectNo = sub.subjectNo
where stuResult >= 80 and subName = '数据库'
3.7 分组和过滤
SELECT j.jname,MAX(salary) maxsalary FROM job j
INNER JOIN emp e
WHERE j.id = e.job_id
GROUP BY j.jname -- 以什么分组
HAVING maxsalary > 20000 --对分组过后的数据在增设条件
4. mysql常用函数
https://dev.mysql.com/doc/refman/5.7/en/sql-function-reference.html
-
常用函数
SELECT ABS(-8) SELECT CEILING(4.4) SELECT FLOOR(5.4) SELECT RAND() SELECT SIGN(2) -- 负数为-1,0为0,正数为1
-
与字符串相关的函数
SELECT CHAR_LENGTH('我真的醉了') -- 返回字符串长度 SELECT CONCAT('我','真的','醉了') -- 拼接字符串 SELECT INSERT('我醉了',2,0,'真的') -- 指定位置替换 SELECT LOWER('HELLO') SELECT UPPER('hello') SELECT INSTR('Tacit',i) -- 返回第一次出现子串的索引 SELECT REPLACE('我真的醉了','真的','假的') -- 替换 SELECT SUBSTR('我真的醉了',3,5) -- 截取子串 SELECT REVERSE('清晨我上马')
-
与时间有关的函数
SELECT CURRENT_DATE() -- 获取当前日期 SELECT CURDATE() -- 获取当前日期 SELECT NOW() -- 获取当前时间 SELECT LOCALTIME() -- 本地时间 SELECT SYSDATE() -- 系统时间 SELECT YEAR(NOW()) -- 年 SELECT MONTH(NOW()) -- 月 SELECT DAY(NOW()) -- 日 SELECT HOUR(NOW()) -- 时 SELECT MINUTE(NOW()) -- 分 SELECT SECOND(NOW()) -- 秒
-
系统函数
SELECT SYSTEM_USER() -- 当前用户 SELECT USER() -- 用户 SELECT VERSION() -- 版本
-
聚合函数
SELECT COUNT(ename) FROM emp -- 会忽略null值 SELECT COUNT(*) FROM emp -- 不会忽略null值,本质计算行数 SELECT COUNT(1) FROM emp -- 不会忽略null值,本质计算行数 SELECT SUM(salary) FROM emp -- 求和 SELECT AVG(salary) FROM emp -- 平均值 SELECT MAX(salary) FROM emp -- 最大值 SELECT MIN(salary) FROM emp -- 最小值
-
数据库级别的MD5加密
-
什么是MD5
将你的密码经行加密,这种加密过程是不可逆的。
INSERT INTO student -- 插入时加密 VALUES(5,'wangwu',MD5('123456'),'男',NULL,NULL,NULL),(6,'mazi',MD5('123456'),'男',NULL,NULL,NULL) -- 查询 SELECT *FROM student WHERE NAME = 'wangwu' AND pwd = MD5('123456') -- 插入后加密 UPDATE student SET pwd = MD5(pwd) WHERE id = 5
-
5. 事务
事务原则
-
原子性(Atomically)
要么都执行,要么都不执行。
-
一致性(Consistency)
事务前后的数据完整性要保持一致。
-
持久性(Durability)
事务一旦提交不可逆,将被持久化到数据库中。
-
隔离性(Isolation)
事务之间互不干扰,即当每个用户开启一个事务时,所操作的数据不会影响到其他用户。
隔离所导致的问题
-
脏读
指一个事务读取了另一个事务还没提交的数据。
-
不可重复读
在一个事务内读取表中的某一行数据,多次读取的结果不同(这不一定是错误,只是某些场合不对)
-
虚读(幻读)
是指在一个事务内读取到了别人插入的数据,导致前后读取不一致。
-- mysql 默认自动开启事务
-- 手动处理事务:
SET autocommit = 0 -- 关闭自动提交
START TRANSACTION-- 开启事务
--事务:模拟转账
UPDATE emp SET bonus = bonus - 333 WHERE id = '1002'
UPDATE emp SET bonus = bonus + 333 WHERE id = '1003'
COMMIT -- 提交事务
ROLLBACK -- 回滚事务
SET autocommit = 1 -- 开启自动提交
-- 了解
SAVEPOINT 保存点名
ROLLBACK TO SAVEPOINT 保存点名
RELEASE SAVEPOINT 保存点名
6. 索引
在一个表中,主键索引只有一个,而唯一索引可以有多个
- 主键索引(Pramary Key)
- 唯一的标识,主键不可重复,只能由一个列作为主键
- 唯一索引(UNIQUE KEY)
- 避免重复的列出现,唯一索引可以重复,多个列都可以标识为唯一索引
- 常规索引(KEY/INDEX)
- 默认的
- 全文索引(FullTest)
- 快速定位数据,某些特定的数据库中才拥有
-- 显示索引信息
SHOW INDEX FROM emp
-- 增加一个全文索引
ALTER TABLE db3.`emp` ADD FULLTEXT INDEX `ename`(`ename`);
-- explain 分析sql执行的状况
explain select* from student -- 非全文索引
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wnMpJGMa-1625487662129)(C:\\Users\\2020\\AppData\\Roaming\\Typora\\typora-user-images\\image-20210416163437827.png)]
-
创建的索引在数据量大的时候才有明显的效果。
-
索引不是越多越好。
-
不要对经常变动的数据加索引。
-
小数据量的表不需要加索引。
-
索引一般加在常用来查询的字段上。
索引的数据结构
hash类型的索引
Btree: InnoDB的默认数据结构~
CodingLabs - MySQL索引背后的数据结构及算法原理
以上是关于Mysql的主要内容,如果未能解决你的问题,请参考以下文章