SQL数据库与Python交互
准备数据
创建数据表
-- 创建京东数据库
create database jingdong charset=utf
-- 使用数据库
use jingdong
-- 创建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);
插入数据
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 超极本','超级本','联想','4999',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,'hmz-t3w 头戴显示设备','笔记本配件','索尼','6999',default,default);
insert into goods values(0,'商务双肩背包','笔记本配件','索尼','99',default,default);
- 简单练习
-- 查询每种类型中最贵的电脑信息
select * from goods
inner join (
select cate_name,
max(price) as max_price,
min(price) as min_price,
avg(price) as avg_price,
count(*)
from goods
group by cate_name) as goods_new_info
on goods.cate_name=goods_new_info.cate_name and
goods.price=goods_new_info.max_price);
上述操作相当于将查询的结果作为一个表,再进行查询操作
- 创建商品分类表
create table if not exists goods_cates(
id int unsigned primary key auto_increment,
name varchar(40) not null);
- 查询goods表中商品分类,并将分组结果写入到goods_cates数据表
select cate_name from goods group by cate_name;
insert into goods_cates(name) select cate_name from goods group by cate_name;
- 同步表数据,通过goods_cates数据表来更新goods表
update goods as g inner join goods_cates as c on g.cate_name=c.name set g.cate_name=c.id;
- 修改表结构
查看goods表结构会发现,cate_name的类型是varchar但现在改为存储数字了,所以需要重命名并修改类型和约束
alter table goods change cate_name cate_id int unsigned not null;
- 为了限制cate_id下的数值只能是goods_cates表中的id,需要给其添加外键
alter table goods add foreign key (cate_id) references goods_cates(id);
- 再对goods表中的brand_name进行以上相同的操作,即新建表并关联外键
-- 显示brand列表
select brand_name from goods group by brand_name;
-- 创建商品分类
! 在创建分表的同时把数值插入!
create table if not exists 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;
! 注意这里必须取别名name
-- 更新goods表中的brand_name
update goods as g inner join goods_brands as b on g.brand_name=b.name set g.brand_name=b.id;
-- 重命名brand_name为brand_id并添加外键约束
alter table goods change brand_name brand_id int unsigned not null;
alter table goods add foreign key(brand_id) references goods_brands(id);
再次说明:在实际开发中很少用到外键,会极大降低表更新的效率
- 如何取消外键?
-- 查看外键名称
show create table goods;
-- 最后会显示创建外键的名称
-- 如:CONSTRAINT `goods_ibfk_1` FOREIGN KEY (`cate_id`) REFERENCES `goods_cates` (`id`),
-- goods_ibfk_1就是外键名称
alter table goods drop foreign key 外键名称;
Python中操作MySQL
步骤

导入模块
import pymysql
# 如果只用到pymysql模块可以from pymysql import *
# 多模块混用还是使用单独的导入方式
1.创建Connection连接
conn = pymysql.connect(host="localhost", port="3306", user="root", password="123456", database="jingdong", charset="utf8")
2.获取Cursor对象
cursor = conn.cursor()
以上两步是使用的必须操作,之后则根据操作不同编写
使用sql语句
查询
cursor.execute("select * fromo goods;")
'''此时会返回生效的行数,而不是表格
这是一条查询语句,当执行查询语句的时候,会将查询的结果存储在游标cursor中'''
cursor.fetchone()
'''此条执行后会按次序提取数据,每次提取一行,返回结果是元组'''
cursor.fetchmany(3)
'''从当前次序取3条数据组成元组返回'''
cursor.fetchall()
'''从当前次序显示所有剩余数据'''
...
...
...
cursor.close()
conn.close()
'''查询完后记得关闭游标和连接!!!'''
添加、修改、删除
增删改操作通过execute()进行操作后,需要使用 连接对象.commit() 来提交完成操作
cursor.execute("""insert into goods_cates (name) values ("硬盘")""")
conn.commit()
'''如果输入错误,可以使用rollback()回滚,如下'''
conn.rollback()
关于SQL注入
实验代码
import pymysql
class JD(object):
def __init__(self):
self.conn = pymysql.connect(host="localhost", port=3306, user="root", password="123456", database="jingdong", charset="utf8")
self.cursor = self.conn.cursor()
def __del__(self):
self.cursor.close()
self.conn.close()
def execute_sql(self, sql):
self.cursor.execute(sql)
for temp in self.cursor.fetchall():
print(temp)
def show_all_items(self):
sql = "select * from goods;"
self.execute_sql(sql)
def show_cates(self):
sql = "select * from goods_cates;"
self.execute_sql(sql)
def show_brands(self):
sql = "select * from goods_brands''"
self.execute_sql(sql)
def add_brands(self):
item_name = input("输入新商品分类名称:")
sql = """insert into goods_brands (name) values('%s')""" % item_name
self.cursor.execute(sql)
self.conn.commit()
def get_info_by_name(self):
find_name = input("请输入想要查询的商品名:")
sql = "select * from goods where name='%s';" % find_name
print("----->%s<-----" % sql)
self.cursor.execute(sql)
@staticmethod
def print_menu():
print("-----京东-----")
print("1.所有的商品")
print("2.所有的商品分类")
print("3.所有的商品品牌分类")
print("4.添加一个商品分类")
print("5.查询指定商品信息")
return input("请输入功能对应的序号:")
def run(self):
while True:
num = self.print_menu()
if num == "1":
self.show_all_items()
elif num == "2":
self.show_cates()
elif num == "3":
self.show_brands()
elif num == "4":
self.add_brands()
elif num == "5":
self.get_info_by_name()
else:
print("输入有误,请重新输入")
def main():
# 1.创建京东对象
jd = JD()
# 调用run运行
jd.run()
if __name__ == '__main__':
main()
当选择5,并且输入 ’ or 1=1 or '1 时,会显示所有的商品信息,这是因为执行了sql语句:
select * from goods where name=’’ or 1=1 or ‘1’;,导致将整个数据库输出
这就是SQL注入
如何防止?
- 将输入内容存入表格,然后使用execute来自动拼接sql语句和列表,如下
def get_info_by_name(self):
find_name = input("请输入想要查询的商品名:")
sql = "select * from goods where name='%s';"
print("----->%s<-----" % sql)
self.cursor.execute(sql, [find_name])
print(self.cursor.fetchall())
这篇笔记详细介绍了如何使用Python与MySQL数据库进行交互,包括创建数据表、插入数据、查询、修改表结构、以及处理SQL注入问题。文中提供了创建连接、获取Cursor对象、执行SQL语句(查询、添加、修改、删除)的步骤,并举例说明了SQL注入的危害和防范措施。

1888

被折叠的 条评论
为什么被折叠?



