文章目录
- 1、前言
- 1.1、语句分类
- 1.2、常用数据结构
- 2、操作数据库及表
- 3、增加、删除、修改(DML)
- 4、查询(DQL,重点)
- 1、查询指定字段
- 2、As(别名)
- 3、distinct(去重)
- 4、表达式
- 5、where条件语句
- 逻辑操作符
- 模糊查询
- 5、联表查询(JOIN)
- 5.1、INEER JOIN(内连接)
- 5.2、左连接(LEFT JOIN)
- 5.3、右连接(RIGHT JOIN)
- 5.4、全连接(FULL JOIN)
- 6、分页、排序
- 6.1、分页(LIMIT)
- 6.2、排序(ORDER BY)
- 7、子查询或嵌套查询
- 8、MySQL函数(count,sum...)
- 9、分组过滤(GROUP BY,HAVING)
- 10、三大范式
1、前言
1.1、语句分类
名称 | 解释 | 命令 |
DDL(数据定义语言) | 定义和管理数据对象,如数据库,数据表等 | CREATE、DROP、ALTER |
DML(数据操作语言) | 用于操作数据库中锁包含的数据 | insert、update、delete |
DQL(数据查询语言) | 用于查询数据库 | select |
DCL(数据控制语言) | 用于管理数据库的语言,包括管理权限及数据更改 | GRANT、commit、rollback |
1.2、常用数据结构
2、操作数据库及表
数据库:
-
create database 数据库名
;创建数据库 -
use 数据库名
;使用数据库 -
drop database 数据库名
;删除数据库 -
show 数据库名
;查看数据库
数据表
创建表:
create table [if not exists] `表名`(
'字段名1' 列类型 [属性][索引][注释],
'字段名2' 列类型 [属性][索引][注释],
#...
'字段名n' 列类型 [属性][索引][注释]
)[表类型][表字符集][注释];
实例:
-- 目标 : 创建一个school数据库
-- 创建学生表(列,字段)
CREATE TABLE IF NOT EXISTS `student` (
`id` int(4) NOT NULL AUTO_INCREMENT COMMENT '学号',
`name` varchar(30) NOT NULL DEFAULT '匿名' COMMENT '姓名',
`sex` varchar(2) NOT NULL DEFAULT '男' COMMENT '性别',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
-
COMMENT
;注释 -
AUTO_INCREMENT
;表示自增 -
ENGINE=InnoDB
;选择引擎为InnoDB -
DEFAULT CHARSET=utf8
;编码格式
修改表:
-
ALTER TABLE 旧表名 RENAME AS 新表名
:修改表名 -
ALTER TABLE 表名 ADD字段名 列属性[属性]
:添加字段
修改字段 :
-
ALTER TABLE 表名 MODIFY 字段名 列类型[属性]
:插入一个字段
例:ALTER TABLE grade MODIFY newname VARCHAR(20) FIRST
:(将字段newname插入到表的第一个位置) -
ALTER TABLE 表名 CHANGE 旧字段名 新字段名 列属性[属性]
:修改字段 -
ALTER TABLE 表名 DROP 字段名
:删除字段
删除数据表:
-
DROP TABLE [IF EXISTS] 表名
IF EXISTS为可选 , 判断是否存在该数据表
如删除不存在的数据表会抛出错误
其他:
1. 可用反引号(`)为标识符(库名、表名、字段名、索引、别名)包裹,以避免与关键字重名!中文也可以作为标识符!
2. 每个库目录存在一个保存当前数据库的选项文件db.opt。
3. 注释:
单行注释 # 注释内容
多行注释 /* 注释内容 */
单行注释 -- 注释内容 (标准SQL注释风格,要求双破折号后加一空格符(空格、TAB、换行等))
4. 模式通配符:
_ 任意单个字符
% 任意多个字符,甚至包括零字符
单引号需要进行转义 \'
5. CMD命令行内的语句结束符可以为 ";", "\G", "\g",仅影响显示结果。其他地方还是用分号结束。delimiter 可修改当前对话的语句结束符。
6. SQL对大小写不敏感 (关键字)
7. 清除已有语句:\c
3、增加、删除、修改(DML)
增加(insert):
INSERT INTO 表名[(字段1,字段2,字段3,...)] VALUES('值1','值2','值3')
示例:
insert into `user`(id,username) values (1,'好好玩')
修改(update):
UPDATE 表名 SET column_name=value [column_name2=value2,...] [WHERE condition];
示例:
UPDATE student set address='上海',name='很好' WHERE id=1009
-- 修改id=1009的那行,多个修改用逗号隔开
删除(delete):
DELETE FROM 表名 [WHERE condition];
示例:
-- 删除数据(不推荐,会删除所有数据)
delete from `user`
-- 删除id=1005以及id=1023的数据
delete from student where id=1005 or id=1023
truncate 命令:
作用:清空表的数据,表的结构、索引、约束不会变
TRUNCATE [TABLE] table_name;
示例:
-- 清空学生表
TRUNCATE student
delete 与 truncate的区别:
- 相同:都能删除表的数据且不删除表的结构,但是truncate更快
- 不同:使用truncate会重置自增,且不会对事务有影响
4、查询(DQL,重点)
select语法:
SELECT [ALL | DISTINCT]
{* | table.* | [table.field1[as alias1][,table.field2[as alias2]][,...]]}
FROM table_name [as table_alias]
[left | right | inner join table_name2] -- 联合查询
[WHERE ...] -- 指定结果需满足的条件
[GROUP BY ...] -- 指定结果按照哪几个字段来分组
[HAVING] -- 过滤分组的记录必须满足的次要条件
[ORDER BY ...] -- 指定查询记录按一个或多个条件排序
[LIMIT {[offset,]row_count | row_countOFFSET offset}];
-- 指定查询的记录从哪条至哪条,分页
-- [ ] 括号代表可选的 , { }括号代表必选得
1、查询指定字段
-- 查询所有学生信息
select * from student
-- 查询指定字段(查询学生表中的id和name字段)(id,name)
select id,name from student
2、As(别名)
作用:可以给数据列或者表取一个新别名,后续可以使用这个新别名代替数据列或者表名
-- 为列取别名(as可以省略)
SELECT studentid AS 学id,studentname AS nameFROM student;
-- 为表取别名(as可以省略)
SELECT studentid AS id,studentname AS name FROM student AS s;
-- 使用as,为查询结果取一个新名字
-- CONCAT()函数拼接字符串
SELECT CONCAT('姓名:',studentname) AS 新姓名 FROM student;
3、distinct(去重)
作用:去掉SELECT查询返回的记录结果中重复的记录 ( 返回所有列的值都相同 ) , 只返回一条
-- 查看哪些同学参加了考试(学号) 去除重复项
-- 查看哪些同学参加了考试,但是学生id可能重复
SELECT studentid FROM score;
-- 了解:DISTINCT 去除重复项 , (默认是ALL)
SELECT DISTINCT studentid FROM score;
4、表达式
-- selcet查询中可以使用表达式
SELECT @@auto_increment_increment; -- 查询自增步长
SELECT VERSION(); -- 查询版本号
SELECT 100*3-1 AS 计算结果; -- 表达式
-- 学员考试成绩集体提分一分查看
SELECT studentid,studentscore+1 AS '提分后' FROM score;
5、where条件语句
逻辑操作符
-- 满足条件的查询(where)
SELECT studentid,studentscore FROM score;
-- 查询考试成绩在95-100之间的,AND也可以写成 &&
SELECT studentid,studentscore
FROM score
WHERE studentscore>=95 AND studentscore<=100;
-- 除了1000号同学,要其他同学的成绩
SELECT studentid,studentscore
FROM score
WHERE studentid!=1000;
模糊查询
-- 模糊查询
-- =============================================
-- LIKE : % (代表0到任意个字符) _ (一个字符)
-- 查询姓刘的同学的学号及姓名
SELECT studentid,studentname FROM student
WHERE studentname LIKE '刘%';
-- 查询姓刘的同学,后面只有一个字的
SELECT studentid,studentname FROM student
WHERE studentname LIKE '刘_';
-- 查询姓刘的同学,后面只有两个字的
SELECT studentid,studentname FROM student
WHERE studentname LIKE '刘__';
-- 查询姓名中含有 好 字的
SELECT studentid,studentname FROM student
WHERE studentname LIKE '%好%';
-- =============================================
-- IN
-- 查询学号为1000,1001,1002的学生姓名
SELECT studentid,studentname FROM student
WHERE studentidIN (1000,1001,1002);
-- 查询地址在北京,南京,河南洛阳的学生
SELECT studentid,studentname,address FROM student
WHERE address IN ('北京','南京','河南洛阳');
-- =============================================
-- NULL 空 : is null
-- 查询出生日期没有填写的同学
SELECT studentname FROM student
WHERE birthday IS NULL;
-- 查询出生日期填写的同学
SELECT studentname FROM student
WHERE birthday IS NOT NULL;
-- 查询没有写家庭住址的同学(空字符串不等于null)
SELECT studentname FROM student
WHERE Address='' OR Address IS NULL;
5、联表查询(JOIN)
七种join:
现在有两张表A,B
A:
B:
5.1、INEER JOIN(内连接)
求的结果是A和B的交集
-- inner join 内连接
select A.name,subject,score
from A INNER JOIN B
ON A.studentid=B.studentid
-- 注意,在这里可以使用where,但是其他连接不能,只能使用on
-- 虽然结果一样
执行结果:
5.2、左连接(LEFT JOIN)
求的是表A中的所有值,在B中没有的会使用NULL代替
-- LEFT JOIN 左连接
select A.name,subject,score
from A LEFT JOIN B
ON A.studentid=B.studentid
执行结果:
5.3、右连接(RIGHT JOIN)
求的是所有在表B中有的数据,若是在A中没有,则用NULL代替
-- RIGHT JOIN 右连接
select A.name,subject,score
from A RIGHT JOIN B
ON A.studentid=B.studentid
执行结果:
5.4、全连接(FULL JOIN)
求的是A表和B表中的并集
6、分页、排序
6.1、分页(LIMIT)
作用:缓解数据库压力,给人的体验更好
语法 :
-- LIMIT m,n 从第m+1行开始,查询n条数据
SELECT * FROM table_name LIMIT 起始行,页面大小
示例:
-- 分页 LIMIT 0,3 :从第一行开始,查询3条
select * from B LIMIT 0,3
执行结果:
6.2、排序(ORDER BY)
升序(ASC):
-- 升序 ASC
select * from B ORDER BY score ASC
执行结果:
降序(DESC):
-- 降序
select * from B ORDER BY score DESC
执行结果:
7、子查询或嵌套查询
本质就是在where里面嵌套一个查询语句,类似
where (select * from )
-- 子查询 查询参与了考试学生姓名与学号
SELECT studentid,`name`
FROM A
WHERE A.studentid in (
SELECT studentid FROM B
)
执行结果:
8、MySQL函数(count,sum…)
-- ================ 内置函数 ================
-- 数值函数
abs(x) -- 绝对值 abs(-10.9) = 10
format(x, d) -- 格式化千分位数值 format(1234567.456, 2) = 1,234,567.46
ceil(x) -- 向上取整 ceil(10.1) = 11
floor(x) -- 向下取整 floor (10.1) = 10
round(x) -- 四舍五入去整
mod(m, n) -- m%n m mod n 求余 10%3=1
pi() -- 获得圆周率
pow(m, n) -- m^n
sqrt(x) -- 算术平方根
rand() -- 随机数
truncate(x, d) -- 截取d位小数
-- 时间日期函数
now(), current_timestamp(); -- 当前日期时间
current_date(); -- 当前日期
current_time(); -- 当前时间
date('yyyy-mm-dd hh:ii:ss'); -- 获取日期部分
time('yyyy-mm-dd hh:ii:ss'); -- 获取时间部分
date_format('yyyy-mm-dd hh:ii:ss', '%d %y %a %d %m %b %j'); -- 格式化时间
unix_timestamp(); -- 获得unix时间戳
from_unixtime(); -- 从时间戳获得时间
-- 字符串函数
length(string) -- string长度,字节
char_length(string) -- string的字符个数
substring(str, position [,length]) -- 从str的position开始,取length个字符
replace(str ,search_str ,replace_str) -- 在str中用replace_str替换search_str
instr(string ,substring) -- 返回substring首次在string中出现的位置
concat(string [,...]) -- 连接字串
charset(str) -- 返回字串字符集
lcase(string) -- 转换成小写
left(string, length) -- 从string2中的左边起取length个字符
load_file(file_name) -- 从文件读取内容
locate(substring, string [,start_position]) -- 同instr,但可指定开始位置
lpad(string, length, pad) -- 重复用pad加在string开头,直到字串长度为length
ltrim(string) -- 去除前端空格
repeat(string, count) -- 重复count次
rpad(string, length, pad) --在str后用pad补充,直到长度为length
rtrim(string) -- 去除后端空格
strcmp(string1 ,string2) -- 逐字符比较两字串大小
-- 聚合函数
count() -- 返回满足条件的语句行数
sum(); -- 求和
max(); -- 最大值
min(); -- 最小值
avg(); -- 平均值
-- 其他常用函数
md5(); -- md5加密
default();
9、分组过滤(GROUP BY,HAVING)
分组(GROUP BY):
-- 分组 GROUP BY
-- 查询每个科目的平均分
SELECT `subject`,AVG(`score`) 平均分 FROM B
GROUP BY `subject`
执行结果:
过滤(HAVING):
当使用分组后需要过滤需要使用此语句
-- 查询语文的平均成绩
SELECT `subject`,AVG(`score`) 平均分 FROM B
GROUP BY `subject`
HAVING `subject`='语文'
-- 分组后过滤不能用where,只能用having
执行结果:
10、三大范式
为什么需要数据规范化?
不合规范的表设计会导致的问题:
- 信息重复:造成数据冗余,浪费空间
- 更新异常:当使用外键时,更新可能发生异常
- 插入异常:当使用外键时,插入可能发生异常
- 删除异常:当使用外键时,删除可能发生异常
三大范式:
三大范式实际上就是我们创建数据库表的一种规范
我们常用的是第一范式(1NF)、第二范式(2NF)、第三范式(3NF),即“三大范式”
第一范式(1NF):要求每一列都是不可分割的原子数据项,例:
上表中的个人信息可以拆分为性别和年龄,如下:
满足了第一范式第二范式(2NF):在第一范式的基础上,要求表中的每列都和主键相关,即每个表只完成一件事,例:
上表中,一个订单可能有不同的产品,所以此表的主键是订单号和产品号联合主键,但是从表中可发现,产品数量与订单号和产品号有关,但订单金额仅和订单号有关,产品价格也仅与产品号有关,所以需要调整,才满足第二范式,如下:
进行了分表之后,满足了第二范式第三范式(3NF):在第一、第二范式的基础上,要求每一列都和主键直接相关,而不是间接相关
如上表,辅导员性别与主键学号并无直接关联,而是和辅导员直接关联,所以修改如下
分表之后,满足了第三范式