1.1.数据库相关概念
1.什么是数据库服务器
数据库服务器就是一个软件(比如mysql软件)将数据库软件安装在电脑上,当前电脑就是一个数据库服务器。就可以对外提供存取数据的服务
在一个数据库服务器中可以创建多个数据库(dataBases),每一个数据库都是一个单独的仓库。
2.什么是数据库
数据库就是存储和管理数据的仓库,通常情况下,一个网站的中的所有数据会存放在一个数据库中
3.什么是表
一个数据库中可以创建多张表,每张表用于存储一类信息(数据库)
4.什么是表记录
一张表中可以包含多行表记录,每一行表记录用于存储某一个具体的数据
1.2 什么是SQL语言
SQL是一门用于操作关系型数据库的通用的语言(使用SQL可以操作所有的关系型数据库)
- 使用SQL可以操作数据库、表、表记录
- 创建数据库、删除数据库、修改数据库、查询数据库
- 创建表、删除表、修改表、查询表
- 新增表记录、删除表记录、修改表记录、查询表记录
- 使用SQL也可以操作存储过程/视图/索引等
提示:SQL是一个标准通用的操作关系型数据库的语言(普通话),每个数据库厂商为了增强自己数据库的功能,都提供了支持自己数据库的语言,称之为数据库的方言,方言在各个数据库中是不通用的!
1.2数据库及表操作
1.2.1创建,删除,查看数据库
提示: 1)SQL语句对大小写不敏感。推荐关键字使用大写,自定义的名称(库名,表名,列名、别名等)使用小写
SHOW DATABASES; 查看当前数据库服务
CREATE DATABASE mydb1; 创建mydb1库
2)并且在自定义名称时,针对多个单词不要使用驼峰命名,而是使用下划线连接。(例如:tab_name,而不是 tabName )
-- 01.查看mysql服务器中所有数据库
show databases; -- 查看所有库
-- 02.进入某一数据库(进入数据库后,才能操作库中的表和表记录)
-- 语法:USE 库名;
use test; 进入test数据库
show tables; 查看test库中的所有表
-- 03.查看当前数据库中的所有表
show tables; 查看test库中的所有表
-- 04.删除mydb1库
-- 语法:DROP DATABASE 库名;
drop database mydb1; 删除不存在的库,这个写法错误
drop database if exists mydb1; 如果存在mydb1,则删除;
-- 05.重新创建mydb1库,指定编码为utf8
-- 语法:CREATE DATABASE 库名 CHARSET 编码;
-- 需要注意的是,mysql中不支持横杠(-),所以utf-8要写成utf8;
create database mydb1 charset utf8; -- 建库时,最好指定编码,如果不指定,这个库的编码有可能是latin1
-- 如果不存在则创建mydb1;
create database if not exists mydb1 charset utf8;
-- 06.查看建库时的语句(了解, 并验证数据库库使用的编码)
-- 语法:SHOW CREATE DATABASE 库名;
show create database mydb1;
1.2.2创建,删除,查看表
-- 07.进入mydb1库,删除stu学生表(如果存在)
-- 语法:DROP TABLE 表名;
use mydb1; drop table if exists stu; -- 如果存在则删除
-- 08.创建stu学生表(编号[数值类型]、姓名、性别、出生年月、考试成绩[浮点型]),建表的语法:
CREATE TABLE 表名( 列名 数据类型, 列名 数据类型, ... 列名 数据类型 );
SQL语句:
use mydb1; create table stu( id int, name varchar(50), -- 50表示name这一列,最多能存50个字符 gender varchar(10), birthday date, score double );
-- 09.查看stu学生表结构
-- 语法:desc 表名
desc stu;
1.2.3新增,修改,删除表记录
-- 10.往学生表(stu)中插入记录(数据)
-- 语法:INSERT INTO 表名(列名1,列名2,列名3...) VALUES(值1,值2,值3...);
insert into stu(id,name,gender,birthday,score) value(1,'tom','male','2000-1-1',85); -- 如果插入的有中文数据,在cmd中,先 set names gbk; 再插入,可以防止中文乱码(或者中文数据插入失败) insert into stu value(2,'孙尚香','female','2001-2-3',90); insert into stu value(3,'后裔','male','2002-3-4',78);
提示
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;-- score+=10 错误写法,mysql不支持+=
-- 13.修改stu表中编号为1的学生成绩,将成绩改为83分
update stu set score=83 where id=1;
提示:where子句用于对记录进行筛选过滤,保留符合条件的记录,将不符合条件的记录剔除。
-- 14.删除stu表中所有的记录
-- 删除语法: DELETE FROM 表名 [where子句]
delete from stu; -- 删除所有记录
-- 仅删除符合条件的(例如,删除id大于1的记录)
delete from stu where id>1;
1.3查询表记录
-- 准备数据
1.3.1 基础查询
SELECT 语句用于从表中选取数据。结果被存储在一个结果表中(称为结果集)。
语法:SELECT 列名称 | * FROM 表名
提示:1)*(星号)为通配符,表示查询所有列。
2)但使用 *(星号)有时会把不必要的列也查出来了,并且效率不如直接指定列名
-- 15.查询emp表中的所有员工,显示姓名,薪资,奖金
select * from emp; -- *表示查询emp表中的所有列 select name,sal,bonus from emp; -- 查询指定的列
-- 16.查询emp表中的所有部门和职位
select dept,job from emp;
思考:如果查询的结果中,存在大量重复的记录,如何剔除重复记录,只保留一条?
-- 在select之后、列名之前,使用DISTINCT 剔除重复的记录
select distinct dept,job from emp;
1.3.2WHERE子句查询
WHERE子句查询语法:SELECT 列名称 | * FROM 表名称 WHERE 列 运算符 值
WHERE子句后面跟的是条件,条件可以有多个,多个条件之间用连接词(or | and)进行连接。
下面的运算符可在 WHERE 子句中使用:
-- 17.查询emp表中【薪资大于3000】的所有员工,显示员工姓名、薪资
select name, sal from emp where sal>3000;
-- 18.查询emp表中【总薪资(薪资+奖金)大于3500】的所有员工,显示员工姓名、总薪资
select name, sal+bonus from emp where sal+bonus > 3500;
-- ifnull(列名, 值)函数: 判断指定的列是否包含null值,如果有null值,用第二个值替换null值
select name, sal+ifnull(bonus,0) from emp where sal+ifnull(bonus,0) > 3500;
-- 注意查看上面查询结果中的表头,如何将表头中的 sal+bonus 修改为 "总薪资"
-- 使用as
可以为表头指定别名(格式:列名 as 别名)
select name as 姓名, sal+ifnull(bonus,0) as 总薪资 from emp where sal+ifnull(bonus,0) > 3500;
-- 另外as
可以省略
-- 19.查询emp表中【薪资在3000和4500之间】的员工,显示员工姓名和薪资
select name,sal from emp
where sal>=3000 and sal<=4500;
-- and:必须同时满足and两边的条件
-- 提示: 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;
-- or: 或,只要满足or两边中的任何一个条件即可!
-- 或者使用 in
select name,sal from emp
where sal in(1400,1600,1800);
-- in:只要sal是in后面括号中的任何一个值,就算符合条件!
-- 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);
-- not表示对条件进行取反
-- 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值
select name,sal,bonus from emp where sal>3000 and ifnull(bonus,0)<600;
-- 24.查询没有部门的员工(即部门列为null值)
select * from emp where dept is null; -- 查询dept列为null的
-- 思考:如何查询有部门的员工(即部门列不为null值)
select * from emp where not(dept is null); -- 查询dept列不为null的 -- 或 select * from emp where dept is not null; -- 查询dept列不为null的
1.3.3 模糊查询
LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式。
可以和通配符(%、_)配合使用,其中"%"表示0或多个任意的字符
,"_"表示一个任意的字符
。
语法:SELECT 列 | * FROM 表名 WHERE 列名 LIKE 值
示例:
-- 25.查询emp表中姓名中以"刘"字开头的员工,显示员工姓名。
select name from emp
where name like '刘%';
-- %表示匹配0个、1个或多个任意字符
-- 26.查询emp表中姓名中包含"涛"字的员工,显示员工姓名。
select name from emp
where name like '%涛%';
-- %涛%, 表示匹配某一列包含涛的记录,'涛'可能在开头、结尾或中间某一个位置
-- 27.查询emp表中姓名以"刘"开头,并且姓名为两个字的员工,显示员工姓名。
-- 以'刘'开头,姓名为两个字的员工 select name from emp where name like '刘_'; -- _(下划线)表示任意一个字符 -- 以'刘'开头,姓名为三个字的员工 select name from emp where name like '刘__';
1.3.3 多行函数查询
多行函数也叫做聚合(聚集)函数,根据某一列或所有列进行统计。
常见的多行函数有:
多行函数 | 作用 |
---|---|
COUNT( 列名 | * ) | 统计结果集中指定列的记录的行数。 |
MAX( 列名 ) | 统计结果集中某一列值中的最大值 |
MIN( 列名 ) | 统计结果集中某一列值中的最小值 |
SUM( 列名 ) | 统计结果集中某一列所有值的和 |
AVG( 列名 ) | 统计结果集中某一列值的平均值 |
提示:1)多行函数不能用在where子句中
2)多行函数和是否分组有关,分组与否会直接影响多行函数的执行结果。
3)多行函数在统计时会对null值进行过滤,直接将null值丢弃,不参与统计。
-- 28.统计emp表中薪资大于3000的员工个数
-- 查询薪资大于3000的员工有哪些?
select * from emp where sal>3000;
-- count:用于统计行数
select count(*) from emp where sal>3000; -- 7
select count(id) from emp where sal>3000; -- 7
select count(bonus) from emp where sal>3000; -- 6
-- 由于bonus中有null值,在统计时,null值直接别丢弃,不参与统计
多行函数需要注意的问题:
- 多行函数和是否分组有关,如果查询结果中的数据没有经过分组,默认整个查询结果是一个组,多行函数就会默认统计当前这一个组的数据。产生的结果只有一个。
- 如果查询结果中的数据经过分组(分的组不止一个),多行函数会根据分的组进行统计,有多少个组,就会统计出多少个结果。
1.3.4 分组查询
GROUP BY 语句根据一个或多个列对结果集进行分组。
在分组的列上我们可以使用 COUNT,SUM,AVG,MAX,MIN等函数。
语法:SELECT 列 | * FROM 表名 [WHERE子句] GROUP BY
列;
-- .对emp表,按照部门对员工进行分组,查看分组后效果。
-- 按照部门分组(3个组) select * from emp group by dept; -- 对上面3个组的人数进行统计 select dept,count(*) from emp group by dept;
1.3.5 排序查询
使用 ORDER BY 子句将结果集中记录根据指定的列排序后再返回
语法:SELECT 列名 FROM 表名 ORDER BY 列名 [ASC|DESC]
ASC(默认)升序,即从低到高;DESC 降序,即从高到低。
-- .对所有员工的薪资进行升序(从低到高)排序,显示员工姓名、薪资。
-- 按照薪资进行排序,默认是升序(asc),即从低到高 select name,sal from emp order by sal; select name,sal from emp order by sal asc;
-- .对emp表中所有员工的奖金进行降序(从高到低)排序,显示员工姓名、奖金。
-- 按照奖金进行降序排序 select name,bonus from emp order by bonus desc;
1.3.6 分页查询
在mysql中,通过limit进行分页查询,查询公式为:
limit (页码-1)*每页显示记录数, 每页显示记录数
-- .查询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;
-- .求emp表中薪资最高的前3名员工的信息,显示姓名和薪资
-- 按照薪资对员工信息进行排序,降序排序 select name,sal from emp order by sal desc; -- 在上面查询的基础上,分页查询,每页显示3条,查询第一页 select name,sal from emp order by sal desc limit 0, 3;
1.3.7 其他函数
函数名 | 解释说明 |
---|---|
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是分隔符 |
-- .查询emp表中所有【在1993和1995年之间出生】的员工,显示姓名、出生日期。
select name,birthday from emp where birthday between 1993 and 1995; -- birthday(日期) 和 1993、1995不能比较,因为类型不同? -- 解决方案1:将1993、1995转换成日期后,再和birthday进行比较 select name,birthday from emp where birthday between '1993-1-1' and '1995-12-31';? -- 解决方案2:将birthday中的年份取出,和1993、1995进行比较 select name,birthday from emp where year(birthday) between 1993 and 1995;