Mysql笔记
目录
sql的DML
增加语句
删除语句和truncate
更新语句
replace语句
select查询语句
简单的查询
等值判断
不等判断
逻辑运算符
查询时的别名使用
常见的条件查询
分组
分组后筛选
结果排序
分页功能
分表
外键和多表关联
表与表之间的关联关系
多表关联查询
SQL中的函数
聚合函数
count(*) 和 count(1)和count(列名)区别
数值型函数
sql的DML
有关数据表的DML操作:INSERT INTO、DELETE、TRUNCATE、UPDATE、SELECT、条件查询、查询排序、聚合函数、分组查询
增加语句
就是给某张表进行数据插入
insert INTO table_name[(field1 [, field2 ……]) values(value1 [, vaule2 ……]) [,()]];
操作:
insert into t_user value(null,"晓晓",21,"女",null,null);
insert into t_user(name,age,gender) values("小柳",18,"男");
插入多条数据:
insert into t_user(name,age,gender) values("小王",18,"男"),("笑笑",20,"女");
删除语句和truncate
删除语言,请注意删除的条件!!!如果不带条件,则删除全表。
delete from table_name [where 条件];
truncate table table_name;
操作:
删除id=4的数据:
delete from user where id=4;
删除全部数据:
delete from user;
truncate table user;
更新语句
更新就是修改表中的数据
update table_name set 字段1=新值 [, 字段2=新值, 字段3=字段3 + 1] [where 条件];
操作:
update t_user set age = 30 where id = 1;
update t_user set age = 20, mark="xw" where id = 4;
update t_user set age = age + 1 ;
replace语句
该语句是集更新和插入为一体的一个语句;如果表中没有这条数据,则执行插入,否则执行更新。
操作:
因为没有,所以插入数据
replace into t_user(id, name, mark) values(100, "test", "test");
有数据,所以更新
replace into t_user(id, name, mark) values(100, "test", "testest");
select查询语句
select *|字段1 [, 字段2 ……] from 表名称 [, 表名称2……] [where 条件] [group by 字段 [having 分组后的筛选]] [order by 字段 [desc|asc] [字段2 [desc|asc] ……]] [limit 分页]
简单的查询
select 字段列表 from 表名称 where 条件
操作:
查询所有数据:
select * from t_user;
查询需要的字段信息:
select id,name,age from t_user;
查询一个字段,一个等值条件:
select name from t_user where id = 1;
等值查询:
select age from t_user where name="lili";
select * from t_user where age=19;
alter table t_user add birthday datetime default now();
select * from t_user where birthday='2025-03-23 14:07:19';
select语句中的特殊情况:
对数值型数据列、变量、常量可以使用算数操作符创建表达式(+ - * /)
对日期型数据列、变量、常量可以使用部分算数操作符创建表达式(+ -)
运算符不仅可以在列和常量之间进行运算,也可以在多列之间进行运算。
SELECT last_name, salary, salary*12
FROM employees;
补充:+ 说明
-- MySQL的+默认只有一个功能:运算符
SELECT 100+80; # 结果为180
SELECT '123'+80; # 只要其中一个为数值,则试图将字符型转换成数值,转换成功做预算,结果为203
SELECT 'abc'+80; # 转换不成功,则字符型数值为0,结果为80
SELECT 'This'+'is'; # 转换不成功,结果为0
SELECT 'This'+'30is'; # ?猜测下这个结果是多少?
SELECT NULL+80; # 只要其中一个为NULL,则结果为NULL
等值判断
条件中,出现了相等值的判断,一般采用
=
进行判断。
=
判断两次的值是否相等
is
判断空null
is not null
来判断不为空
<=>
可以判断null或者普通值
不等判断
!=
不等于
<>
也是不等于
逻辑运算符
逻辑运算符是多条件关联的一种方式
and
or
not
注意:在sql中,如果要提升条件的运行顺序,或者提高条件的优先级别,则需要使用括号来提升。
查询时的别名使用
查询时,将结果的显示字段,使用一个其他名称来代替,就是别名。
查询总条数:
select count(*) from t_user;
别名显示表格:
mysql> select count(*) as count from t_user;
常见的条件查询
where:
select name from t_user where age = 19;
WHERE中比较运算符:
select name from t_user where age < 22;
其他比较运算符:
select name,age from t_user where age between 21 and 22;
使用IN运算符:
select name,age from t_user where age in (20,21,22);
使用LIKE运算符:
select name,age from t_user where name like '_i%';
使用IS NULL运算符查询包含空值的记录
逻辑运算符:and、or、not
使用正则表达式:REGEXP
<列名> regexp '正则表达式'
select * from product where product_name regexp '^2018';
分组
sql中,分组是一种统计概念。查询的数据,进行数据分析时,可能需要将相同的数据分成一组
group by 字段
select gender from t_user group by gender;
分组后筛选
如果直接在分组后的结果集上进行条件判断,将条件写在where中,会报错,因为:结果集是分组后才能做的判断,而where实在查询前的条件判断。所以不能使用where,必须使用having。但是having必须写在group by之后!没有分组,就不能写having,但是分组可以没有having。
select gender, count(gender) from t_user group by gender having count(gender) > 5;
结果排序
将查询结果,以特定的顺序展示(升序或者降序)。
order by 字段
order by 字段 asc|desc;
order by 字段 asc|desc, 字段2 ;
正序排:
select * from t_user order by age;
select * from t_user order by age asc;
倒序排:
select * from t_user order by age desc;
在年龄按正序的基础上,id按倒序
select * from t_user order by age , id desc;
分页功能
select语句,查询数据时,可能结果会非常多,此时就不能直接展示,分页展示。
总数量(all_data):查询 select count(*)
每页展示的数量(page_size):程序员定
当前页(cur_page):默认第一页,用户自己点击选择
总页数(all_page):总数量 % 每页的数量 == 0 整除后的商 : 商 + 1
limit num # 查询多少条
limit num1, num2; # num1: 偏移量, num2 : 每页的数量
limit cur_page * (page_size - 1), page_size;
分表
为什么分表:
数据直接都存储在一张表中:
如果数据很大,性能会出现问题
将不同的数据,如果放在同一个表中,可能数据冗余
数据冗余,会导致数据可能出错
将不同的类型,采用不同的数据表进行存储,如果两张表或者多张表之间存在关联关系,则可以采用外键来描述这种关联关系。
主表中,一般是一个字段,改字段一般是从表的主键。
操作:
我们要先创建从表,否则数据插不进去
创建班级:
create table grade(
id int auto_increment,
name varchar(50) unique,
primary key(id)
);
插入数据:
insert into grade(name) value("Java精品班"), ("python数据分析班"), ("网络安全班"), ("云原生高级班");
创建学生:
create table student(
id int primary key auto_increment,
name varchar(50) unique,
gender enum("F", "M"),
age int default 18,
adddress varchar(255),
class_id int
);
插入数据:
insert into student(name, class_id) values("张三", 1);
insert into student(name, class_id) values("李四", 2);
insert into student(name, class_id) values("王五", 1);
insert into student(name, class_id) values("林一", 3);
insert into student(name, class_id) values("萧二", 1);
insert into student(name, class_id) values("小五", 4);
当我们插入一条错误数据,那么我们查询时是无法查到的:
insert into student(name, class_id) values("张三666", 44);
如果要避免出现这种情况,必须加入外键约束!
外键和多表关联
外键:指的是两张或者多张表之间关联关系的字段。
外键约束:是表的约束,是约束表在插入外键数据时能够正确的插入。
添加约束:
方法一:在创建表时添加
create table student(
id int primary key auto_increment,
name varchar(50) unique,
gender enum("F", "M"),
age int default 18,
adddress varchar(255),
class_id int,
foreign key(class_id) references grade(id)
);
方法二:用alter
ALTER TABLE 表名 ADD CONSTRAINT 外键名 FOREIGN KEY(外键字段名) REFERENCES 外表表名(主键字段名)
表与表之间的关联关系
当表与表之间存在了外键,这就意味着,这两张表之间存在某种关联关系。
一旦表存在了关联关系,则会进行外键设计,如何设计外键,设计在哪张表中?
-
一对一 :外键可以设计在任意一张表中
-
一对多 :外键必须设计在多方
-
多对多 :创建第三张表,来专门描述两张表的关联关系
多表关联查询
当两张或者多张表之间存在了关联关系,往往多表查询,如果查询。
交叉连接
内连接
外链接
左外连接
右外连接
自连接
全连接
自然连接 【不建议使用,直到就行】数据库自动使用相同字段名称完成外键关联
select *|字段 [,……] from 表名称 [,表名称] ……
操作:
交叉连接(cross join):
在查询多表时,不指定表的关联关系,数据只能全部匹配
引发笛卡尔积现象
select * from student, grade;
sql98的标准写法:
select * from student cross join grade;
内连接(常用):
select * from student, grade where student.class_id = grade.id;
select * from student, grade where student.class_id=grade.id and student.name='张三';
sql98的内连接方式时,如果不指定关联条件,不管怎么写,都是交叉连接:
select * from student inner join grade;
select * from student join grade;
正确写法:
select * from student inner join grade on (student.class_id=grade.id);
select * from student join grade on (student.class_id=grade.id) where student.name = "张三";
内连接,只能查询出,存在关联关系的数据,如果不存在关联关系,如目前没有班级的学生,目前没有学生的班级
select * from student cross join grade on (student.class_id=grade.id) where student.name = "张三";
如果要将这些没关联关系的数据查询出来,则需要使用外连接
左引进,那么就是他的左边的表;右引进,那么就是他的右边的表
select * from student left (outer) join grade on (student.class_id=grade.id);
select * from student right (outer) join grade on (student.class_id=grade.id);
联合查询:(union 、union all)
联合查询,必须保证查询的多条SQL返回的结果 结构必须一致,所以联合查询常见于查询一张表
(select * from student where class_id = "1") union (select id, name from student where id > 3); --会报错
(select * from student where class_id = "1") union all (select * from student where id > 3);
自连接查询:
表的外键指向自身
创建一个模块表
create table board (
id int primary key auto_increment,
name varchar(50) unique not null,
intro text,
parent_id int,
foreign key(parent_id) references board(id)
);
一层一层嵌套:
前端板块:html、css
后端板块:java、python
硬件板块:嵌入式
python:python基础、django、python GUI开发
css:css2、css3
insert into board(name, parent_id) values("前端板块", null);
insert into board(name, parent_id) values("后端板块", null);
insert into board(name, parent_id) values("硬件板块", null);
insert into board(name, parent_id) values("html", 1);
insert into board(name, parent_id) values("css", 1);
insert into board(name, parent_id) values("java", 2);
insert into board(name, parent_id) values("python", 2);
insert into board(name, parent_id) values("嵌入式", 3);
insert into board(name, parent_id) values("python基础", 7);
insert into board(name, parent_id) values("django", 7);
insert into board(name, parent_id) values("python GUI开发", 7);
insert into board(name, parent_id) values("css2", 5);
insert into board(name, parent_id) values("css3", 5);
查看一级板块名称:
select name from board where parent_id is null;
查看前端板块的二级名称: (子查询)
select name from board where parent_id = (select id from board where name = "前端板块");
select * from board as b, (select id from board where name = "前端板块") as t where b.parent_id = t.id;
查询二级名称
select name from (select * from board where parent_id is not null) as t where t.parent_id in (1, 2, 3);
如果数据为空,则改为0;如果不为空,则不变
select ifnull(age,0) from student where id = 3;
select ifnull(age,0) from student where id = 2;
SQL中的函数
SQL中默认提供很多系统内置函数,帮助开发者实现各种需要的功能。
聚合函数
聚合函数对一组值进行运算,并返回单个值。也叫组合函数。
COUNT(*|列名) 统计行数
AVG(数值类型列名) 平均值
SUM (数值类型列名) 求和
MAX(列名) 最大值
MIN(列名) 最小值
除了COUNT()以外,聚合函数都会忽略NULL值。
count(*) 和 count(1)和count(列名)区别
count(1) and count(*)
当表的数据量大些时,对表作分析之后,使用count(1)还要比使用count()用时多了! 从执行计划来看,count(1)和count()的效果是一样的。 但是在表做过分析之后,count(1)会比count(*)的用时少些(1w以内数据量),不过差不了多少。
如果count(1)是聚索引,id,那肯定是count(1)快。但是差的很小的。 因为count(),自动会优化指定到那一个字段。所以没必要去count(1),用count(),sql会帮你完成优化的 因此:count(1)和count(*)基本没有差别!
count(1) and count(字段) 两者的主要区别是 (1) count(1) 会统计表中的所有的记录数,包含字段为null 的记录。 (2) count(字段) 会统计该字段在表中出现的次数,忽略字段为null 的情况。即不统计字段为null 的记录。
count(*) 和 count(1)和count(列名)区别
执行效果上: count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计。
执行效率上:
列名为主键,count(列名)会比count(1)快
列名不为主键,count(1)会比count(列名)快
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count(*)
如果有主键,则 select count(主键)的执行效率是最优的
如果表只有一个字段,则 select count(*)最优。
数值型函数
函数名称 | 作用 |
---|---|
ABS | 求绝对值 |
SQRT | 求平方根 |
POW 和 POWER | 两个函数的功能相同,返回参数的幂次方 |
MOD | 求余数 |
CEIL 和 CEILING | 两个函数功能相同,都是返回不小于参数的最小整数,即向上取整 |
FLOOR | 向下取整,返回值转化为一个BIGINT |
RAND | 生成一个0~1之间的随机数,传入整数参数是,用来产生重复序列 |
ROUND | 对所传参数进行四舍五入 |
SIGN | 返回参数的符号 |