学习目标
-
能够自己动手将对应的数据导入到数据库
-
知道外键约束的作用
-
了解E-R模型的组成部分
-
能够举例说出生活中 1对1 1对多 多对多关系的例子
-
知道一个表结构设计是否满足范式的要求
-
能够说出 python 操作数据库的步骤
-
能够 connect 方法创建连接对象
-
能够使用连接对象的 cursor()方法 创建游标对象
-
能够使用游标对象的 execute()方法执行 SQL 语句
-
能够使用游标对象的 close()方法关闭游标对象
-
能够使用连接对象的 close()方法关闭连接对象
-
能够使用游标对象的 fetchall()方法取出所有数据
-
能够使用游标对象的 fetchone()方法取出一条数据
-
能够说出如何避免 SQL 注入问题
数据准备
1. 数据准备
-
创建数据表
-- 创建 "京东" 数据库
create database jing_dong charset=utf8;
-- 使用 "京东" 数据库
use jing_dong;
-- 创建一个商品goods数据表
create table goods(
id int unsigned primary key auto_increment not null,
name varchar(150) not null,
cate_name varchar(40) not null,
brand_name varchar(40) not null,
price decimal(10,3) not null default 0,
is_show bit not null default 1,
is_saleoff bit not null default 0
);
-
插入数据
-- 向goods表中插入数据
insert into goods values(0,'r510vc 15.6英寸笔记本','笔记本','华硕','3399',default,default);
insert into goods values(0,'y400n 14.0英寸笔记本电脑','笔记本','联想','4999',default,default);
insert into goods values(0,'g150th 15.6英寸游戏本','游戏本','雷神','8499',default,default);
insert into goods values(0,'x550cc 15.6英寸笔记本','笔记本','华硕','2799',default,default);
insert into goods values(0,'x240 超极本','超级本','联想','4880',default,default);
insert into goods values(0,'u330p 13.3英寸超极本','超级本','联想','4299',default,default);
insert into goods values(0,'svp13226scb 触控超极本','超级本','索尼','7999',default,default);
insert into goods values(0,'ipad mini 7.9英寸平板电脑','平板电脑','苹果','1998',default,default);
insert into goods values(0,'ipad air 9.7英寸平板电脑','平板电脑','苹果','3388',default,default);
insert into goods values(0,'ipad mini 配备 retina 显示屏','平板电脑','苹果','2788',default,default);
insert into goods values(0,'ideacentre c340 20英寸一体电脑 ','台式机','联想','3499',default,default);
insert into goods values(0,'vostro 3800-r1206 台式电脑','台式机','戴尔','2899',default,default);
insert into goods values(0,'imac me086ch/a 21.5英寸一体电脑','台式机','苹果','9188',default,default);
insert into goods values(0,'at7-7414lp 台式电脑 linux )','台式机','宏碁','3699',default,default);
insert into goods values(0,'z220sff f4f06pa工作站','服务器/工作站','惠普','4288',default,default);
insert into goods values(0,'poweredge ii服务器','服务器/工作站','戴尔','5388',default,default);
insert into goods values(0,'mac pro专业级台式电脑','服务器/工作站','苹果','28888',default,default);
insert into goods values(0,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
insert into goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
insert into goods values(0,'x3250 m4机架式服务器','服务器/工作站','ibm','6888',default,default);
insert into goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
2. SQL语句强化
-
查询类型cate_name为 '超极本' 的商品名称、价格
select name,price from goods where cate_name = '超级本';
-
显示商品的种类
select cate_name from goods group by cate_name;
-
求所有电脑产品的平均价格,并且保留两位小数
select round(avg(price),2) as avg_price from goods;
-
显示每种商品的平均价格
select cate_name,avg(price)
from goods group by cate_name;
-
查询每种类型的商品中 最贵、最便宜、平均价、数量
select cate_name,max(price),min(price),avg(price),count(*)
from goods group by cate_name;
-
查询所有价格大于平均价格的商品,并且按价格降序排序
select id,name,price from goods
where price > (select round(avg(price),2) as avg_price from goods)
order by price desc;
分表操作
学习目标
-
能够把一个表中的数据放到多个表中
1. 分表操作步骤
-
问题表
由于只存在商品信息一张表 其中既有商品信息又有分类名称和品牌名称。当把某个商品信息删除后,本不应该删除的<独立于商品信息的分类和品牌>等信息结果也随着删除商品信息而删除,那么此时存在删除异常
-
解决方案
如图我们创建两张表 商品种类表 商品品牌表 存储对应的信息 就不会出现删除异常了
-
最终效果
有了这样的最终表,我们的商品种类和商品品牌信息就能独立保存起来
-
分表操作步骤
-
第一步: 创建商品种类表
-
第二步: 同步数据到商品种类表中
-
第三步: 更新商品信息表数据
-
第四步: 修改商品信息表表结构
2. 根据商品表中的分类信息创建分类表
-
创建 "商品分类"表
由于只存在一张表 其中既有商品信息又有分类名称和品牌名称。当把某种分类或者品牌的商品全部删除后,本不应该删除<独立于商品信息的分类和品牌>等信息结果也随着删除商品信息而删除,那么此时存在删除异常。
为解决删除异常问题,则必须再创建分类表和品牌表单独用来存储数据。
-- 创建商品分类表
create table if not exists goods_cates(
id int unsigned primary key auto_increment,
name varchar(40) not null
);
-
将分类信息导入到分类表中
-
查询goods表中商品的种类
select cate_name from goods group by cate_name;
-
将分组结果写入到goods_cates商品种类数据表
insert into goods_cates (name)
select cate_name from goods group by cate_name;
-
将商品表中的分类名称更改为分类名称对应的分类id
-
通过goods_cates数据表来更新goods表
update goods g
join goods_cates gc
on g.cate_name=gc.name
set g.cate_name=gc.id;
3. 根据商品表中的品牌信息创建品牌表
-
创建 "商品品牌表" 表并导入品牌名称
-
通过create table ...select来创建数据表并且同时写入记录,一步到位
-- select brand_name from goods group by brand_name;
-- 在创建数据表的时候一起插入数据
-- 注意: 需要对brand_name 用as起别名,否则name字段就没有值
create table goods_brands (
id int unsigned primary key auto_increment,
name varchar(40) not null) select brand_name as name from goods group by brand_name;
-
使用商品品牌表中的信息更新商品表信息
-
通过goods_brands数据表来更新goods数据表
update goods as g inner join goods_brands as b on g.brand_name=b.name set g.brand_name=b.id;
4. 修改商品表表结构
-
查看 goods 的数据表结构,会发现 cate_name 和 brand_name对应的类型为 varchar
desc goods;
-
通过alter table语句修改表结构
alter table goods
change cate_name cate_id int unsigned not null,
change brand_name brand_id int unsigned not null;
pymysql-查操作
学习目标
-
能够说出 python 操作数据库的步骤
-
能够 connect 方法创建连接对象
-
能够使用连接对象的 cursor()方法 创建游标对象
-
能够使用游标对象的 execute()方法执行 SQL 语句
-
能够使用游标对象的 close()方法关闭游标对象
-
能够使用连接对象的 close()方法关闭连接对象
1. pymysql模块的作用
问题: 如何使用客户端将100000行数据插入到数据库?
回答: 大家会发现如果用之前客户端几乎是不可能完全这个任务的, 因为我们不可能去构造出那个插入10w行数据的SQL. 可是,如果我们有一个功能能够插入一行数据,借助程序强大的特点-重复,就可以轻而易举的就将10w行数据收入麾下. 那么在Python中实现这样的操作可以使用pymysql这个模块完成.
2. Python 中操作 MySQL 步骤
操作步骤:
-
导入模块
-
创建连接
-
创建游标
-
执行sql
-
关闭游标
-
关闭连接
步骤详解:
-
引入模块
from pymysql import connect
-
创建连接(创建connection连接对象)
作用: 用于建立与数据库的连接, 调用pymysql模块中的connect()方法.
conn=connect(参数列表)
* 参数host:连接的mysql主机,如果本机是'localhost'
* 参数port:连接的mysql主机的端口,默认是3306
* 参数database:数据库的名称
* 参数user:连接的用户名
* 参数password:连接的密码
* 参数charset:通信采用的编码方式,推荐使用utf8
-
创建游标(通过连接对象获取游标) 游标的作用: 执行sql语句(使用频度最高的语句为select、insert、update、delete)
-
获取游标对象
# 调用connection对象的cursor()方法获取游标对象
cur = conn.cursor()
-
执行sql(这里需要使用游标执行sql语句)
-
通过游标执行sql
# excute中放入sql语句即可执行对应的sql语句
cur.execute(sql)
# 执行完毕SQL语句,会返回受影响的行数
num = 游标对象.execute(sql)
-
获取结果集中的一条数据
# 获取的数据会以元组形式放回
# 如 (1,'妲己',18)
cur.fetchone()
-
获取结果集中的所有数据
# 执行查询时,获取结果集的所有行,一行构成一个元组,再将这些元组装入一个元组返回
# 如 ((1,'公孙离',20),(2,'妲己',18))
cur.fetchall()
-
关闭游标
# 注意游标的关闭应该在连接关闭前
cur.close()
-
关闭连接
# 注意这里注意 连接和游标的关闭先后顺序 先关闭游标后关闭连接
conn.close()
3. pymysql练习
import pymysql
# 创建和数据库服务器的连接
conn = pymysql.connect(host='localhost', port=3306, user='root', password='mysql',database='python_test_1', charset='utf8')
# 获取游标
cursor = conn.cursor()
# 创建sql语句
sql = """select * from hero;"""
# 数据库中受影响的的数据行数
row_count = cursor.execute(sql)
print("SQL语句执行影响的行数%d" % row_count)
# 取出结果集中一行 返回的结果是一行数据 如: (1, '妲己', 2)
data1 = cursor.fetchone()
print(data1)
# 取出结果集中的所有数据 返回的结果是所有数据
# 如: ((第一行数据),(第二行数据),(第三行数据), ...)
# ((1, '妲己', 2), (2, '李白', 1), (3, '程咬金', 3), (4, '亚瑟', 5), (5, '荆轲', 99))
data2 = cursor.fetchall()
print(data2)
# 也可以使用for循环遍历数据
for line in cursor.fetchall():
print(line)
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
总结
操作步骤:
-
导入模块
-
创建连接
-
创建游标
-
执行sql
-
关闭游标
-
关闭连接
pymysql-增删改操作
学习目标
•能够使用游标对象完成数据库的增删改
1. 数据提交和数据回滚
-
数据提交commit
数据库中的基本操作: 增删改查. 上一个章节中我们知道如何完成对数据库中数据的获取其实也就是查, 比如获取一条数据或者获取所有数据等. 接下来我们学习下如何增删改.
注意:
查数据, 并不会对原有数据库中的数据造成影响. 而增删改这三个操作都会对原有数据库中的数据造成影响. 也就说查数据不会修改原有数据空中的数据, 而增删改会修改原有数据库中的数据.
当对原有数据库中数据有修改时需要使用
# commit()提交数据到数据库
# 这里可以理解为 数据库询问是否确定修改数据 然后commit()就是确定修改的意思
conn.commit()
-
数据回滚rollback()
当我们在使用pymysql对数据进行响应的操作时, 会有可能会有一些错误操作, 这是如果想要数据返回到最原始的状态可以使用数据回滚操作
注意:
数据回滚是需要在 commit() 之前才有效的, 也就是说数据还没有确定修改这时候使用数据回滚才是有效的
# 回滚数据到什么都没做的原始状态 即撤销刚刚所有的修改操作
conn.rollback()
2. pymysql的增删改查操作
在掌握了数据提交commit后, 实际上pymysql的数据的增删改和数据的查就没有什么区别了, 这里仅仅是对sql语句进行修改即可, 其他的操作步骤和原先的查是一样的
import pymysql
# 创建连接
conn = pymysql.connect(host='127.0.0.1',port=3306,user='root',password='mysql',db='python_test_1', charset='utf8')
# 通过连接获取游标
cursor = conn.cursor()
# 删除数据
sql_1 = "delete from hero where id = 5;"
# 增加数据
sql_2 = "insert into hero (name) values ('西部大坏蛋孙悟空');"
# 修改数据
sql_3 = "update hero set kongfuid=444 where id = 4;"
# 执行相应的sql语句即可
row_count = cursor.execute(sql_1)
print("SQL语句执行影响的行数%d" % row_count)
# 回滚数据到什么都不做的状态 即撤销刚刚的修改
# conn.rollback()
# 提交数据到数据库
conn.commit()
# 关闭游标和连接
cursor.close()
conn.close()
总结
数据提交:
-
commit()
数据回滚
-
rollback()