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','男')

注意事项:

  1. 字段与字段之间使用英文隔开
  2. 字段名是可以省略的,但是后面的值必须要一一对应,不能少
  3. 可以同时插入多条语句,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相当于||

注意事项:

  1. column_name 是数据库的列,尽量带上’ '。

  2. 筛选的条件如果不加上会改变所有的列。

  3. 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 Nulla is null操作符为null,结果为真
is not Nulla is not null操作符不为null,结果为真
betweena between b and c若a在b和c之间,则结果为真
likea like bSql匹配,如果a匹配b,则结果为真
ina 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,这样的表可以进行自连接

    如下表:

    categoryidpidcategoryName
    21信息技术
    31软件开发
    43数据库
    51美术设计
    63web开发
    75ps技术
    82办公信息

进行拆分:

1为顶级id的生成一张主表

categoryidcategotyName
2信息技术
3软件开发
5美术设计

在根据原表的pid匹配主表的categoryid生成子类

pidcategoryidcategotyName
34数据库
36web开发
57ps技术
28办公信息
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. 事务

事务原则

  1. 原子性(Atomically)

    要么都执行,要么都不执行。

  2. 一致性(Consistency)

    事务前后的数据完整性要保持一致。

  3. 持久性(Durability)

    事务一旦提交不可逆,将被持久化到数据库中。

  4. 隔离性(Isolation)

    事务之间互不干扰,即当每个用户开启一个事务时,所操作的数据不会影响到其他用户。

隔离所导致的问题

  1. 脏读

    指一个事务读取了另一个事务还没提交的数据。

  2. 不可重复读

    在一个事务内读取表中的某一行数据,多次读取的结果不同(这不一定是错误,只是某些场合不对)

  3. 虚读(幻读)

    是指在一个事务内读取到了别人插入的数据,导致前后读取不一致。

-- 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的主要内容,如果未能解决你的问题,请参考以下文章

mysql 练习

MySQL--题库解析

MySQL习题

mysql语句实战

7_mysql查询之where子句

mysql练习题