MySQL学习分享之sql语句

数据库概述

所谓的数据库就是指存储和管理数据的仓库,早期: 层次式数据库、网络型数据库;现在:关系型数据库、非关系型数据库

什么是关系型数据库?

底层以二维表的形式保存数据的库就是关系型数据库

常见的关系型数据库有哪些?(了解)

  • Sql Server:微软提供,收费,适用于一些中型或大型的项目中,在java中的使用占比不高(.NET中使用的较多)
  • Oracle:甲骨文公司提供,收费,适用于一些大型或者超大型的项目中,在java中的使用占比非常高
  • mysql:瑞典MySQLAB公司提供,免费开源,适用于一些小型或者中型的项目中,在Java中的使用占比较高(小巧轻量)mariadb其实就是MySQL的一个分支,用法和MySQL完全一样。
  • DB2:IBM公司提供,收费,在一些银行、金融等行业中使用较多。在java中的使用占比也不高。
  • Sqlite:迷你数据库,嵌入式设备中(安卓、苹果手机、pad)

数据库相关概念

  1. 什么是数据库服务器

数据库服务器就是一个软件(比如mysql软件)将数据库软件安装在电脑上,当前电脑就是一个数据库服务器。就可以对外提供存取数据的服务,在一个数据库服务器中可以创建多个数据库(dataBases),每一个数据库都是一个单独的仓库。

  1. 什么是数据库

数据库就是存储和管理数据的仓库,通常情况下,一个网站的中的所有数据会存放在一个数据库中。

连接mysql服务器

通过命令行工具可以登录MySQL客户端,连接MySQL服务器,从而访问服务器中的数据。

1、连接mysql服务器:

mysql -uroot -p密码

-u:后面的root是用户名,这里使用的是超级管理员root;

-p:(小写的p)后面的root是密码,这是在安装MySQL时就已经指定的密码;

2、连接mysql服务器并指定IP和端口:

mysql -uroot -proot -h127.0.0.1 -P3306

-h:后面给出的127.0.0.1是服务器主机名或ip地址,可以省略的,默认连接本机;

-P:(大写的P)后面的3306是连接端口,可以省略,默认连接3306端口;

3、退出客户端命令:quit或exit或 \q

4、在cmd中连接mysql服务器之后,可以使用 #、/**/、-- 等符号添加注释

数据库及表操作

创建、删除、查看数据库

提示: (1)SQL语句对大小写不敏感。推荐关键字使用大写,自定义的名称(库名,表名,列名等)使用小写。

(2)并且在自定义名称时,针对多个单词不要使用驼峰命名,而是使用下划线连接。(例如:tab_name,而不是 tabName )

01.查看mysql服务器中所有数据库

SHOW DATABASES;  --查看服务器所有的数据库

02.进入某一数据库(进入数据库后,才能操作库中的表和表记录) 语法:USE 库名;

use mysql;  --进入到名为'mysql'的数据库
show tables; --查询当前库中的所有表

查看已进入的库(了解)

select database();

03.查看当前数据库中的所有表

use test;
show tables;

04.删除mydb1库 语法:DROP DATABASE 库名;

drop database mydb1; --删除mydb1库,但如果删除的库不存在,则会报错

思考:当删除的库不存在时,如何避免错误产生?

drop database if exists mydb1;
-- 如果mydb1库存在则删除,如果不存在,也就不执行删除操作

05.重新创建mydb1库,指定编码为utf8

语法:CREATE DATABASE 库名 CHARSET 编码; 需要注意的是,mysql中不支持横杠(-),所以utf-8要写成utf8;

create database mydb1 charset utf8;
-- 如果不存在则创建mydb1;
create database if not exists mydb1 charset utf8;

06.查看建库时的语句(并验证数据库库使用的编码)

语法:SHOW CREATE DATABASE 库名;

show create database mydb1;

创建、删除、查看表

07.进入mydb1库,删除stu学生表(如果存在)

语法:DROP TABLE 表名;

use mydb1; --进入mydb1库
drop table if exists stu; --如果存在stu表,则删除

08.创建stu学生表(编号[数值类型]、姓名、性别、出生年月、考试成绩[浮点型]),建表的语法:

CREATE TABLE 表名(
	列名 数据类型,
	列名 数据类型,
	...
  	列名 数据类型
);

SQL语句:

-- 如果存在,则删除stu表
drop table if exists stu;
-- 创建stu学生表
create table stu(
    id int ,
    name varchar(50),
    gender varchar(10),
    birthday date,
    score double
);

给id添加主键约束并设置自增,给gender添加非空约束,auto_increment自增

-- 如果存在,则删除stu表
drop table if exists stu;
-- 创建stu学生表
create table stu(
    id int primary key auto_increment,
    name varchar(50),
    gender varchar(10) not null,
    birthday date,
    score double
);

09.查看stu学生表结构

语法:desc 表名

desc stu;

新增、更新、删除表记录

10.往学生表(stu)中插入记录(数据)

语法:INSERT INTO 表名(列名1,列名2,列名3...) VALUE(值1,值2,值3...);

-- 如果是在cmd中执行插入记录的语句,先 set names gbk; 再插入记录!
--由于id已经设置了主键自增,所以在插入数据时,id可以不用给值
insert into stu(id,name,gender,birthday,score) value(null,'tom','male','2000-3-4',89);
insert into stu value(null,'john','male','2002-5-6',78);
insert into stu value(null,'andy','female','2004-7-6',91);
-- 查询学生表中的所有记录
select * from stu;
(1)当为所有列插入值时,可以省写列名,但值的个数和顺序必须和声明时列的个数和顺序保持一致!
(2)SQL语句中的值为字符串或日期时,值的两边要加上单引号(有的版本的数据库双引号也可以,但推荐使用单引号)。
(3)(针对cmd窗口)在插入数据之前,先设置编码:set names gbk;
或者用以下命令连接mysql服务器:
	mysql --default-character-set=gbk -uroot -proot
等价于:
	mysql -uroot -proot
	set names gbk;

11.查询stu表所有学生的信息

语法:SELECT 列名 | * FROM 表名

select * from stu;

12.修改stu表中所有学生的成绩,加10分特长分

修改语法: UPDATE 表名 SET 列=值,列=值,列=值...[WHERE子句];

update stu set score=score+10;

13.修改stu表中编号为1的学生成绩,将成绩改为83分。

update stu set score=83 where id=1;

修改3号学生的性别为'male',成绩改为99;

update stu set score=99,gender='male' where id=3;

提示:where子句用于对记录进行筛选过滤,保留符合条件的记录,将不符合条件的记录剔除。

14.删除stu表中所有的记录

删除记录语法: DELETE FROM 表名 [where子句]

delete from stu; --删除stu表中所有的记录

仅删除符合条件的

delete from stu where id>2;

查询表记录

基础查询

SELECT 语句用于从表中选取数据。结果被存储在一个结果表中(称为结果集)。

语法:SELECT 列名称 | * FROM 表名

提示:(1) *(星号)为通配符,表示查询所有列。 (2)但使用 *(星号)有时会把不必要的列也查出来了,并且效率不如直接指定列名

15.查询emp表中的所有员工,显示姓名,薪资,奖金

select name,sal,bonus from emp;

16.查询emp表中的所有部门和职位

select dept,job from emp;

思考:如果查询的结果中,存在大量重复的记录,如何剔除重复记录,只保留一条?

在select之后、列名之前,使用DISTINCT 剔除重复的记录

select distinct dept,job from emp;

WHERE子句查询

WHERE子句查询语法:SELECT 列名称 | * FROM 表名称 WHERE 列 运算符 值

WHERE子句后面跟的是条件,条件可以有多个,多个条件之间用连接词(or | and)进行连接

下面的运算符可在 WHERE 子句中使用:

操作符描述
=等于
<> 或 !=不等于
>大于
<小于
>=大于等于
<=小于等于
BETWEEN在某个范围内
LIKE搜索某种模式

17.查询emp表中【薪资大于3000】的所有员工,显示员工姓名、薪资

select name,sal from emp where sal>3000;

18.查询emp表中【总薪资(薪资+奖金)大于3500】的所有员工,显示员工姓名、总薪资

select name,sal+bonus from emp where sal+bonus>3500;

注:null+任何值=null

ifnull(列名, 值)函数: 判断指定的列是否包含null值,如果有null值,用第二个值替换null值

select name,sal+ifnull(bonus,0) from emp
where sal+ifnull(bonus,0)>3500;

使用as可以为表头指定别名

select name as 姓名,sal+ifnull(bonus,0) as 总薪资 from emp
where sal+ifnull(bonus,0)>3500;

另外as可以省略

select name  姓名,sal+ifnull(bonus,0)  总薪资 from emp
where sal+ifnull(bonus,0)>3500;

19.查询emp表中【薪资在3000和4500之间】的员工,显示员工姓名和薪资

select name,sal from emp where sal>=3000 and sal<=4500;

提示: between...and... 在...和...之间

select name,sal from emp where sal between 3000 and 4500;

20.查询emp表中【薪资为 1400、1600、1800】的员工,显示员工姓名和薪资

select name,sal from emp where sal=1400 or sal=1600 or sal=1800;

或者

select name,sal from emp where sal in(1400,1600,1800);

21.查询薪资不为1400、1600、1800的员工,显示员工姓名和薪资

select name,sal from emp where not(sal=1400 or sal=1600 or sal=1800) ;

select name,sal from emp where sal not in(1400,1600,1800);

22.查询emp表中薪资大于4000和薪资小于2000的员工,显示员工姓名、薪资。

select name,sal from emp where sal>4000 or sal <2000;

23.查询emp表中薪资大于3000并且奖金小于600的员工,显示员工姓名、薪资、奖金。

select name,sal,bonus from emp where sal>3000 and bonus<600;

处理null值:null和任何值比较,结果都是false

select name,sal,ifnull(bonus,0) from emp where sal>3000 and ifnull(bonus,0)<600;

24.查询没有部门的员工(即部门列为null值)

select * from emp where dept=null; -- 条件错误,不能=null
select * from emp where dept is null;

思考:如何查询有部门的员工(即部门列不为null值)

select * from emp where not(dept is null);
select * from emp where dept is not null;

模糊查询

LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式。 可以和通配符(%、)配合使用,其中"%"表示0或多个任意的字符,""表示一个任意的字符。

语法:SELECT 列 | * FROM 表名 WHERE 列名 LIKE 值

25.查询emp表中姓名中以"刘"字开头的员工,显示员工姓名。

select name from emp where name like '刘%';

26.查询emp表中姓名中包含"涛"字的员工,显示员工姓名。

select name from emp where name like '%涛%';

27.查询emp表中姓名以"刘"开头,并且姓名为两个字的员工,显示员工姓名。

select name from emp where name like '刘_';

多行函数查询

多行函数也叫做聚合(聚集)函数,根据某一列或所有列进行统计。

常见的多行函数有:

多行函数作用
COUNT( 列名 / * )统计结果集中指定列的记录的行数
MAX( 列名 )统计结果集中某一列值中的最大值
MIN( 列名 )统计结果集中某一列值中的最小值
SUM( 列名 )统计结果集中某一列所有值的和
AVG( 列名 )统计结果集中某一列值的平均值

提示:

  1. 多行函数不能用在where子句中
  2. 多行函数和是否分组有关,分组与否会直接影响多行函数的执行结果。
  3. 多行函数在统计时会对null值进行过滤,直接将null值丢弃,不参与统计。

28.统计emp表中薪资大于3000的员工个数

select count(*) from emp where sal>3000;

29.求emp表中的最高薪资

select max(sal) from emp;

30.统计emp表中所有员工的薪资总和(不包含奖金)

select sum(sal) from emp;

31.统计emp表员工的平均薪资(不包含奖金)

select avg(sal) from emp;

多行函数需要注意的问题:

● 多行函数和是否分组有关,如果查询结果中的数据没有经过分组,默认整个查询结果是一个组,多行函数就会默认统计当前这一个组的数据。产生的结果只有一个。

● 如果查询结果中的数据经过分组(分的组不止一个),多行函数会根据分的组进行统计,有多少个组,就会统计出多少个结果。

例如:统计emp表人数

select count(*) from emp;

结果返回的就是emp表中的所有人数, 再例如:根据性别对emp表中的所有员工进行分组,再统计每组的人数,显示性别和对应人数

select count(*) from emp group by gender;

分组查询

GROUP BY 语句根据一个或多个列对结果集进行分组。

在分组的列上我们可以使用 COUNT,SUM,AVG,MAX,MIN等函数。

语法:SELECT 列 | * FROM 表名 [WHERE子句] GROUP BY 列;

32.对emp表,按照部门对员工进行分组,查看分组后效果。

select name,dept from emp group by dept;
-- 统计分组后,每组的人数
select count(*) from emp group by dept; --3个组,所以会统计出三个结果

33.对emp表按照职位进行分组,并统计每个职位的人数,显示职位和对应人数

--根据job进行分组,统计每个组的人数(每个职位的人数)
select job,count(*) from emp group by job;

34.对emp表按照部门进行分组,求每个部门的最高薪资(不包含奖金),显示部门名称和最高薪资

--如果不分组,直接使用max(sal),这是统计整个emp表中的最高薪资
select max(sal) from emp; -- 5000
--如果根据部门分组,可以分为三个组,再使用max(sal),就是统计每个组的最高薪资
select dept,max(sal) from emp group by dept;

排序查询

使用 ORDER BY 子句将结果集中记录根据指定的列排序后再返回

语法:SELECT 列名 FROM 表名 ORDER BY 列名 [ASC|DESC]

ASC(默认)升序,即从低到高;DESC 降序,即从高到低。

35.对emp表中所有员工的薪资进行升序(从低到高)排序,显示员工姓名、薪资。

--默认是升序,asc可以省略
select name,sal from emp order by sal;
select name,sal from emp order by sal asc;

36.对emp表中所有员工的奖金进行降序(从高到低)排序,显示员工姓名、奖金。

select name,bonus from emp order by bonus desc;

null会看做比0还小的值

分页查询

在mysql中,通过limit进行分页查询,查询公式为:

limit (页码-1)*每页显示记录数, 每页显示记录数

37.查询emp表中的所有记录,分页显示:每页显示3条记录,返回所有页的数据。

--每页显示3条,查询第1页数据
select * from emp limit 0,3;
--每页显示3条,查询第2页数据
select * from emp limit 3,3;
--每页显示3条,查询第3页数据
select * from emp limit 6,3;
--每页显示3条,查询第4页数据
select * from emp limit 9,3;

38.求emp表中薪资最高的前3名员工的信息,显示姓名和薪资

select name,sal from emp order by sal desc limit 0,3;

其他函数

curdate()获取当前日期,格式是:年月日
curtime()获取当前时间 ,格式是:时分秒
sysdate()/now()获取当前日期+时间,格式是:年月日 时分秒
year(date)返回date中的年份
month(date)返回date中的月份
day(date)返回date中的天数
hour(date)返回date中的小时
minute(date)返回date中的分钟
second(date)返回date中的秒
CONCAT(s1,s2..)将s1,s2 等多个字符串合并为一个字符串
CONCAT_WS(x,s1,s2..)同CONCAT(s1,s2,..)函数,但是每个字符串之间要加上x,x是分隔符

39.查询emp表中所有【在1993和1995年之间出生】的员工,显示姓名、出生日期。

-- 将运算符两边的值都转成日期类型,再进行比较
select name,birthday from emp where birthday >= '1993-1-1' and birthday<='1995-12-31';

select name,birthday from emp where birthday between '1993-1-1' and '1995-12-31';
--或者,将日期中的年份提取出来,用年份和年份进行比较
select name,birthday from emp where year(birthday) between 1993 and 1995;

40.查询emp表中本月过生日的所有员工

select * from emp where month(now())=month(birthday);

41.查询emp表中员工的姓名和薪资(薪资格式为: xxx(元) )

select name,concat(sal,'(元)') from emp ;

补充练习:查询emp表中员工的姓名和薪资(薪资格式为: xxx/元 )

select name,concat(sal,'/元') from emp ;
或
select name,concat_ws('/',sal,'元') from emp;

多表查询

连接查询

42.查询部门和部门对应的员工信息

select * from dept,emp;

上面的查询中存在大量错误的数据,一般我们不会直接使用这种查询。 笛卡尔积查询:所谓笛卡尔积查询就是指,查询两张表,其中一张表有m条记录,另一张表有n条记录,查询的结果是m*n条。 虽然笛卡尔积查询中包含大量错误数据,但我们可以通过where子句将错误数据剔除,保留下来的就是正确数据。

select * from dept,emp where dept_id=dept.id;

通过where子句将笛卡尔积查询中的错误数据剔除,保留正确的数据,这就是连接查询!

上面的查询可以换成下面的查询:

--内连接查询,和上面的查询结果一样(把两张表的逗号换成inner join,where换成on)
select * from dept inner join emp on emp.dept_id=dept.id;

左外连接查询

43.查询【所有部门】及部门对应的员工,如果某个部门下没有员工,员工显示为null

select * from dept left join emp on emp.dept_id=dept.id;

左外连接查询:可以将左边表中的所有记录都查询出来,右边表只显示和左边相对应的数据,如果左边表中某些记录在右边没有对应的数据,右边显示为null即可。

右外连接查询

-- 44.查询【所有员工】及员工所属部门,如果某个员工没有所属部门,部门显示为null

select * from dept right join emp
on emp.dept_id=dept.id;

右外连接查询:可以将右边表中的所有记录都查询出来,左边表只显示和右边相对应的数据,如果右边表中某些记录在左边没有对应的数据,可以显示为null。

扩展:如果想将两张表中的所有数据都查询出来(左外+右外并去除重复记录),可以使用全外连接查询,但是mysql又不支持全外连接查询。

可以使用union将左外连接查询的结果和右外连接查询的结果合并在一起,并去除重复的记录。例如:

select * from dept left join emp on emp.dept_id=dept.id
union
select * from dept right join emp on emp.dept_id=dept.id;

需要注意的是:union可以将两条SQL语句执行的结果合并,但是有前提:

(1)两条SQL语句查询的结果列数必须一致

(2)两条SQL语句查询的结果列名、顺序也必须一致

并且union默认就会将两个查询中重复的记录去除(如果不希望去除重复记录,可以使用union all)

end
  • 作者:(联系作者)
  • 更新时间:2022-07-22 16:30
  • 版权声明:自由转载-非商用
  • 转载声明:如果是转载栈主转载的文章,请附上原文链接