1.1 概念
1.2 特点
1.3 作用
1.4 分类
2.1 概念
DBMS (Database Management System),为管理数据库而设计的软件系统
2.2 组成
2.3 SQL语句
2.4 RDBMS的核心元素
3.1 服务端搭建
安装
sudo apt-get install mysql-server
启动
sudo service mysql start
ps -ajx|grep mysql # 查看进程中是否存在MySQL
停止
sudo service mysql stop
3.2 客户端安装
sudo apt-get install mysql-client
mysql -uroot -pmysql #连接命令
quit #退出
3.3 MySQL配置文件
配置文件路径
/etc/mysql/mysql.conf.d/mysqld.cnf
配置文件信息
bind -address 表示服务器绑定的ip,默认为127.0.0.1
port 表示端口,默认为3306
datadir 表示数据库目录,默认为/var/lib/mysql
general_log_file 表示普通日志,默认为/var/log/mysql/mysql.log
log_error表示错误日志,默认为/var/log/mysql/error.log
配置文件操作命令
# 进入目录
cd /etc/mysql/mysql.conf.d
# 编辑配置文件
vi mysqld.cnf
MySQL数据库本身自带命令行工具,但使用上功能性和易用性不是太好。
安装
cd #安装文件所在目录
tar -axvf #安装文件名
cd #解压的安装文件
./start.mysql #运行mysql
5.1 数值
整型
TINYINT #1Bytes
SMALLINT #2Bytes
MEDIUMINT #3Bytes
INT #4Bytes #-2^31~2^31-1或0~2^32-1
BIGINT #8Bytes
浮点型
float #保留6位小数
double #保留16位小数
decimal #定点数 例如:decimal(5,2) 5位数字,其中2位小数
5.2 日期/时间
date 年-月-日
datetime 年-月-日 时:分:秒
timestamp 年-月-日 时:分:秒
time 时:分:秒
year
5.3 字符串(字符)
5.4 枚举类型
6.1 数据完整性
用于保证数据的正确性,核实其约束条件
参照完整性
约束
作用:保证数据完整性和一致性
约束类型
NOT NULL 非空约束
PRIMARY KEY 主键约束
UNIQUE KEY 唯一约束
DEFAULT 默认约束
FOREIGN KEY 外键约束
sudo apt-get install mysql-server
sudo apt-get install mysql-client
sudo service mysql start
mysql -uroot -pmysql
mysql -uroot -p --输入密码
7.5.1 退出数据库
quit
exit
快捷操作:Ctrl+D
7.5.2 显示数据库版本
select version();
快捷操作:Ctrl +Shift +V
7.5.3 显示时间
select now();
7.5.4 快捷操作
Ctrl + a #到行首
Ctrl + l #清屏
Ctrl + e #到行尾
Ctrl + C+回车 #结束
show databases; --查看所有数据库
show create database 数据库名称; --查看创建的数据信息,包括字符集及名称等
select database(); --查看当前使用的数据库
create database 数据库名称 charset=utf8;
use 数据库名称; --使用数据库
drop database 数据库名称; --删除指定数据库
7.8.1 查看表结构
show tables; --查看当前所有的表
desc 表名; --查看表结构
show create table 表名; --查看创建的数据表详细信息
7.8.2 约束
int unsigned --无符号整型
auto_increment --自动增长
not null --非空
primary key --主键
7.8.3 创建数据表
create table heima(
id int unsigned primary key auto_increment not null,
name varchar(20) not null,
age int unsigned default 0,
high decimal(5,2),
gender enum("男","女"),
cls_id int unsigned
);
7.8.4 数据表操作
增
alter table 表名 add 列名 类型; --增加字段
删
alter table drop table 表名; --删除字段
drop table 表名; --删除数据表
改
#修改类型及约束
alter table 表名 modify 列名 类型及约束;
# 重命名
alter table 表名 change 原名 新名 类型及约束;
查
desc 表名; --查看表结构
7.8.5 表数据操作
增
insert into 表名 values(); --全列插入
insert into 表名 (表头1,表头2) values(值1,值2); --部分列插入
insert into 表名 values( ),( ); --多行插入
删
#方法一
delete from 表名 where 条件;
#方法二
alter table 表名 add is_delete bit default 0; --定义is_delete字段来保留并标识删除的数据
update 表名 set is_delete=1 where 条件; --将删除的数据的标志物置1
select * from 表名 where is_delete=1; --查询删除的数据
改
update 表名 set 列名=值;
update 表名 set 列名1=值 where 【条件】;
查
select * from 表名;
select 列1,列2... from 表名;
select 列1 as 别名1, 列名2 as 别名2 from 表名;
文本编辑器
notepad++
sublime Text
8.1 去重查询
select distinct 列名 from 表名;
8.2 起别名查询
字段起别名
select 字段名 as 别名 from 表名;
数据表起别名
select 字段名 from 表名 as 别名;
8.3 where 查询
对数据表中的数据进行筛选,结果为True的记录会出现在结果集中。
select * from 表名 where 条件;
比较运算符:=、>、<、>=、<=、<>或者!=、!>、!<
-- 查询年龄不为18岁的所有学生的名字
select * from students where age != 18;
select * from students where age <> 18;
逻辑运算符:and、or、not
-- 不在 18岁以上的女性 这个范围内的信息
select * from students where not (age>18 and gender="女");
模糊查询:like、%(替代任意多个)、_(替代任意一个)、[ ](指定一个字符、字符串或范围)、[^](指定字符以外的任一个字符)
--查询姓名中 有 "小" 所有的名字
select * from students where name like "%小%";
范围查询:in、between … and …
--查询身高在165-180,年龄在18-34岁的女性的姓名、性别、身高
select name as '姓名',gender as '性别',height as '身高' from students where (height between 165 and 180) and (age between 18 and 34) and (gender = '女');
空值判断:is null、is not null
-- 判非空is not null
select * from students where height is not null;
order排序查询
-- 查询年龄在18到34岁之间的女性,身高从高到矮排序, 如果身高相同的情况下按照年龄从大到小排序
select * from students where (age between 18 and 34) and gender=2 order by height desc, age desc;
--查询身高在165-180的男性或者年龄在20-40的女性,并以年龄升序排序,如果相同则以身高降序排列。
select * from students where (height between 165 and 180 and gender=1) and (age between 20 and 40 and gender=2) order by age asc,height desc;
聚合函数
将当前所在表当做一个组进行统计
count():计算总行数
-- 查询男性有多少人
select count(*) from students where gender=1;
max():计算最大值
-- 查询最大的年龄
select max(age) from students;
min():计算最小值
-- 查询最低身高
select min(height) from students;
sum():求和
-- 计算所有人的年龄总和
select sum(age) from students;
avg():求平均值
-- 计算平均年龄
select avg(age) from students;
--round() 四舍五入取值
-- 计算所有人的平均年龄,保留2位小数
select round(avg(age),2) from students;
8.4 group分组查询
group by 将查询结果按照1个或者多个字段进行分组
group by
-- 按照性别分组,查询所有的性别
select gender from students group by gender;
group by + group_concat()
group_concat(字段名)作用 : 根据分组结果,使用group_concat()来放置每一个分组中某字段的集合
-- 查询同种性别中的姓名
select group_concat(name),gender from students group by gender;
group by + 聚合函数
作用 : 聚合函数在和group by结合使用的时候 统计的对象是每一个分组
-- 计算每种性别中的人数
select gender,count(*) from students group by gender;
-- 查询每组性别的平均年龄
select avg(age),gender from students group by gender;
group by + having
作用 : having作用和where类似,但having只能用于group by对分组后的每组数据过滤 而where是用来过滤表数据
-- 查询平均年龄超过30岁的性别,以及姓名 having avg(age) > 30(重点)
select group_concat(name),gender from students group by gender having avg(age) > 30;
group by + with rollup
with rollup的作用是:在数据表最后新增一行,来记录当前表中该字段对应的操作结果,一般是汇总结果
-- with rollup 汇总的作用(了解)
select count(*),gender from students group by gender with rollup;
8.5 limit分页查询
-- 每页显示2个,显示第4页的信息, 按照年龄从小到大排序
select * from students order by age asc limit 6,2;
8.6 连接查询
当查询结果来源于多个表的时候,需要将多张表的内容连接成一个大的数据集进行汇总显示。
内连接:inner join
查询的结果为两个表符合条件匹配的数据集
-- select ... from 表A inner join 表B;
select * from students inner join classes;
-- 查询 有能够对应班级的学生以及班级信息
select * from students inner join classes on students.cls_id=classes.id;
-- 显示姓名、班级
select students.name,classes.name from students inner join classes on students.cls_id=classes.id;
-- 给数据表起名字
select s.name,c.name from students as s inner join classes as c on s.cls_id=c.id;
on和where的区别:
on 连接条件
where 连接后进行筛选的条件
外连接
左连接:left join
主表在SQL语句的左边,连接后主表中未匹配的从表的数据对应字段以Null展示。
-- 查询每位学生对应的班级信息
select * from students left join classes on students.cls_id=classes.id;
右连接:right join
主表在SQL语句的右边,连接后主表中未匹配的从表的数据对应字段以Null展示。
-- 将数据表名字互换位置,用left join完成
select * from classes right join students on students.cls_id=classes.id;
自连接
Why:加快查询速度,减少数据表占用空间。
source 资源 # 快速导入资源数据库
-- 从sql文件中导入文件 source areas.sql
-- 查询省的名称为“广东省”的所有城市
select city.* from
areas as city
inner join
areas as province
on city.pid=province.aid
where province.atitle="广东省";
8.7 子查询
定义:把一个查询的结果当做另一个查询的条件
分类
语法格式:
--(1)查询出高于平均身高的信息(height)
select * from students where height > (select avg(height) from students);
--(2)查询学生的班级号能够对应的 学生名字
select * from students where cls_id in (select id from classes);
9.1 实战操作
创建数据库
create database 数据库 charset=utf8;
打开数据库
use 数据库;
show databases;查看所有数据库
show create database 数据库;查看创建的数据库信息
创建数据表
create table 数据表 (...);
- desc 数据表;查看数据表结构信息
- show tables; 查看所有的数据表列表
插入数据
insert into 数据库 values(...);
- select * from 数据表;
常用数据表操作
-- 查询类型 cate_name 为 '超级本' 的商品名称 name 、价格 price ( where )
select name,price from goods where cate_name="超级本";
-- 显示商品的种类
-- 1 分组的方式( group by )
select cate_name from goods group by cate_name;
-- 2 去重的方法( distinct )
select distinct cate_name from goods;
-- 求所有电脑产品的平均价格 avg ,并且保留两位小数( round )
select round(avg(price),2) from goods;
-- 显示 每种类型 cate_name (由此可知需要分组)的 平均价格
select avg(price),cate_name from goods group by cate_name;
-- 查询 每种类型 的商品中 最贵 max 、最便宜 min 、平均价 avg 、数量 count
select cate_name,max(price),min(price),avg(price),count(*) from goods group by cate_name;
-- 查询所有价格大于 平均价格 的商品,并且按 价格降序 排序 order desc
-- 1 查询平局价格(avg_price)
select avg(price) as avg_price from goods;
-- 2 使用子查询
select * from goods where price>(select avg(price) as avg_price from goods) order by price desc;
-- 查询每种类型中最贵的电脑信息(难)
-- 1 查找 每种类型 中 最贵的 max_price 价格
select max(price) as max_price,cate_name from goods group by cate_name;
-- 2 关联查询 inner join 每种类型 中最贵的物品信息
select * from goods
inner join
(select max(price) as max_price,cate_name from goods group by cate_name) as max_price_goods
on goods.cate_name=max_price_goods.cate_name and goods.price=max_price_goods.max_price;
数据表优化
优化步骤
(1)创建商品种类表
(2)同步数据到商品种类表中
(3)更新商品信息表数据
(4)修改商品信息表表结构
第一步 创建表 (商品种类表 goods_cates )
create table if not exists goods_cates(
id int unsigned primary key auto_increment,
name varchar(40) not null
);
第二步 同步 商品分类表 数据 将商品的所有 (种类信息) 写入到 (商品种类表) 中
-- 按照 分组 的方式查询 goods 表中的所有 种类(cate_name)
select cate_name from goods group by cate_name;
--插入分组后的数据,注意:语句中没有values关键字
insert into goods_cates(name) (select cate_name from goods group by cate_name);
第三部 同步 商品表 数据 通过 goods_cates 数据表来更新 goods 表
-- 因为要通过 goods_cates表 更新 goods 表 所以要把两个表连接起来
select * from goods inner join goods_cates on goods.cate_name=goods_cates.name;
-- 把 商品表 goods 中的 cate_name 全部替换成 商品分类表中的 商品id ( update ... set )
update (goods inner join goods_cates on goods.cate_name=goods_cates.name) set goods.cate_name=goods_cates.id;
第四部 修改表结构
-- 查看表结构(注意 两个表中的 外键类型需要一致)
desc goods;
-- 修改表结构 alter table 字段名字不同 change,把 cate_name 改成 cate_id int unsigned not null
alter table goods change cate_name cate_id int unsigned not null;
9.2 外键
定义:一个数据表的主键A在另一个数据表B中出现,则称为A是数据表B的外键。
作用:限制无效信息的插入
操作说明
-- 外键的使用
-- 向goods表里插入任意一条数据
insert into goods (name,cate_id,brand_id,price) values('老王牌拖拉机', 10, 10,'6666');
-- 约束 数据的插入 使用 外键 foreign key
-- alter table goods add foreign key (brand_id) references goods_brands(id);
alter table goods add foreign key(cate_id) references goods_cates(id);
alter table goods add foreign key(brand_id) references goods_brands(id);
-- 失败原因 老王牌拖拉机 delete
-- delete from goods where name="老王牌拖拉机";
delete from goods where name="老王牌拖拉机";
-- 如何取消外键约束
-- 需要先获取外键约束名称,该名称系统会自动生成,可以通过查看表创建语句来获取名称
show create table goods;
-- 获取名称之后就可以根据名称来删除外键约束
alter table goods drop foreign key goods_ibfk_1;
alter table goods drop foreign key goods_ibfk_2;
9.3 视图
定义:能够把复杂SQL语句的功能封装起来的一个虚表
特点
操作说明
-- 视图的定义方式
create view 视图名称(一般使用v开头) as select语句;
-- 查出学生的id,姓名,年龄,性别 和 学生的 班级
select s.id,s.name,s.age,s.gender,c.name as cls_name
from students as s
inner join classes as c
on s.cls_id=c.id;
-- 创建上述结果的视图( v_students )
-- create view v_students as
--注意:连接后的字段名不能相同,若相同,需用as其别名区分。
create view v_students as
select s.id,s.name,s.age,s.gender,c.name as cls_name
from students as s
inner join classes as c
on s.cls_id=c.id;
--查看视图
show tables;
-- 删除视图(drop view 视图名字)
drop view v_students;
9.4 事务
定义:Transaction,是指作为一个基本工作单元执行的一系列SQL语句的操作,要么完全地执行,要么完全地都不执行。
应用
A用户和B用户是银行的储户,现在A要给B转账500元,那么需要做以下几件事:
检查A的账户余额>500元;
A 账户中扣除500元 ;
B 账户中增加500元 ;
事务四大特性ACID
原子性(Atomicity)[ætəˈmɪsəti]
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,
要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。
一致性(Consistency)
数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失500元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。)
隔离性(Isolation)
通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则其看到支票帐户的余额并没有被减去500元。)
持久性(Durability)
一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。)
事务的使用
开启事务
开启事务后执行修改命令,变更会维护到本地缓存中,而不维护到物理表中begin; 或者 start transaction;
提交事务
将缓存中的数据变更维护到物理表中commit;
回滚事务
放弃缓存中变更的数据 表示事务执行失败 应该回到开始事务前的状态rollback;
MySQL默认的存储引擎:innodb
- 查看指令:show engines \G;
9.5 索引
定义:一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里所有记录的位置信息。
使用说明
查看表中已有索引
show index from 表名;
创建索引
alter table 表名 add index 索引名【可选】(字段名,…);
删除索引
drop index 索引名称 on 表名;
优缺点
优点:
加快数据的查询速度
缺点:
创建索引会浪费时间和占用磁盘空间,并且随着数据量的增加所耗费的时间会越来越多。
使用原则
经常发生数据更新的表避免使用过多的索引
数据量小的表没有必要使用索引
数据量较大同时不会频发发生数据更改的表可以使用索引
代码实现
-- 创建测试表
create table test_index(title varchar(10));
-- 向表中插入10万条数据
python3 insert_data.py
-- 验证索引性能
-- 没有索引
-- 开启时间检测:
set profiling=1;
-- 查找第1万条数据ha-99999
select * from test_index where title="ha-99999";
-- 查看执行时间
show profiles;
-- 有索引
-- 给title字段创建索引
alter table test_index add index(title);
-- 查找第1万条数据ha-99999
select * from test_index where title="ha-99999";
-- 查看执行时间
show profiles;
9.6 数据库设计三范式
定义:设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,
各种范式呈递次规范,越高的范式数据库冗余越小。
第一范式(1NF): 强调的是字段的原子性,即一个字段不能够再分成其他几个字段。
第二范式(2NF): 满足 1NF的基础上,另外包含两部分内容:
主键可以由多个字段共同组成
create table test ( name varchar(19), id int, primary key (name,id) )
第三范式(3NF): 满足 2NF,另外非主键字段必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键字段 A 依赖于非主键字段 B,非主键字段 B 依赖于主键的情况。
其他范式:巴斯科德范式、第五范式等
9.7 E-R模型及表间关系
9.8 Python连接MySQL
数据库编程:通过使用程序代码的方式去连接MySQL数据库,然后对MySQL数据库进行增删改查的方式。
使用步骤:(调用pymysql)
①导入 pymysql 包
import pymysql
②创建连接对象
connect()
③获取游标对象
连接对象.cursor()
④ pymysql完成数据的查询操作
游标对象.execute()
⑤ 关闭游标和连接
游标对象.close()
连接对象.close()
代码实现
查询操作
# 导入pymysql包
import pymysql
# 创建连接对象
conn = pymysql.connect(host="localhost", port=3306, user="root", password="mysql", database="python_test_1", charset="utf8")
# 获取游标对象
cur = conn.cursor()
# pymysql完成数据的查询操作
sql = "select * from students;"
# 这里content获取的是sql影响的行数
# content = cur.execute(sql)
# print(content)
cur.execute(sql)
content = cur.fetchone()
print(content)
content = cur.fetchall()
print(content)
# 关闭游标和连接
cur.close()
conn.close()
增删改操作
# 导入pymysql包
import pymysql
# 创建连接对象
conn = pymysql.connect(host="localhost", port=3306, user="root", password="mysql", database="python_test_1", charset="utf8")
# 获取游标对象
cs = conn.cursor()
# 增加数据
# sql = "insert into students(name) values('老王')"
# cs.execute(sql)
# 删除数据
# sql = "delete from students where id=18"
# cs.execute(sql)
# 修改数据
sql = "update students set name='老王' where id=1;"
cs.execute(sql)
for i in content:
print(i)
# 提交操作
conn.commit()
# 关闭游标和连接
cs.close()
conn.close()
9.9 SQL语句参数化
目的:防止SQL注入
SQL注入:用户提交带有恶意的数据与SQL语句进行字符串方式的拼接,从而影响了SQL语句的语义,最终产生数据泄露的现象。
参数化实现
# 导入pymysql包
import pymysql
# 创建连接对象
conn = pymysql.connect(host="localhost", port=3306, user="root", password="mysql", database="python_test_1", charset="utf8")
# 获取游标对象
cs = conn.cursor()
# 不安全的方式
# 根据id查询学生信息
# find_name = input("请输入您要查询的学生姓名:")
# sql = "select * from students where name='%s'" % find_name
# # 显示所有的数据
# cs.execute(sql)
# content = cs.fetchall()
# for i in content:
# print(i)
# 安全的方式
# 根据id查询学生信息
find_name = input("请输入您要查询的学生姓名:")
sql = "select * from students where name=%s"
# 显示所有的数据
cs.execute(sql, [find_name])
content = cs.fetchall()
for i in content:
print(i)
# 关闭游标和连接
cs.close()
conn.close()