pymysql模块和SQL注入

目录

1.sql复习和分表操作

2.pymysql模块

2.1 pymysql的使用步骤

2.1 pymysql 增删改

1.数据提交和数据回滚

3.sql注入

1. 什么是SQL注入

2.非安全方式的SQL语句

3.安全方式的SQL语句


1.sql复习和分表操作

# 创建数据库
create database if not exists jing_dong charset = utf8;
# 切换数据库
use jing_dong;
# 创建表
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 超极本', '超级本', '联想', '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);

# 1.查询类型cate_name为 '超极本' 的商品名称、价格
select name, price
from goods
where cate_name = '超级本';
#2.  显示商品的种类
select cate_name
from goods
group by cate_name;
# distinct可以去重
select distinct cate_name
from goods;
# 3.求所有电脑产品的平均价格,并且保留两位小数
select round(avg(price), 2)
from goods;
# 4. 显示每种商品的平均价格
select cate_name, round(avg(price), 2) as avg
from goods
group by cate_name;
# 5. 查询每种类型的商品中 最贵、最便宜、平均价、数量
select cate_name, max(price), min(price), avg(price), count(*)
from goods
group by cate_name;
# 6.查询所有价格大于平均价格的商品,并且按价格降序排序
select *
from goods
where price > (select avg(price) from goods)
order by price desc;




# 创建商品分类表,用于存储所有的商品分类
create table if not exists goods_cates
(
    id   int unsigned primary key auto_increment,
    name varchar(100)
);
# 将商品表中存在的商品分类的名字 写入到 商品分类表
# 1. 得知道现在在商品表中都有哪些商品分类
select cate_name
from goods
group by cate_name;
insert into goods_cates(name)
values ('笔记本'),
       ('游戏本');

# 新的语法,在将查询结果 插入到表中  insert into 表名 select ....
insert into goods_cates(name)
select cate_name
from goods
group by cate_name;

select *
from goods_cates;

# 2. 将goods表中的 cate_name 都修改为 goods_cate中的id的值
update goods as g join goods_cates as gc on g.cate_name = gc.name
set g.cate_name=gc.id;

# update .... set...  更新数据的语法
# goods join goods_cates  连表查询。 条件 g.cate_name = gc.name
# set 后面的 设置更新的数据, 将 g.cate_name=gc.id

# 3. 将cate_name 字段名 修改为 cate_id
alter table goods change cate_name cate_id int unsigned;

# 获取一下 商品的品牌名称
select brand_name from goods group by brand_name;

# 将goods表中的 brand_name 放到 商品品牌表 goods_brands
# 创建表的同时插入数据。  create table xxx() ...select ......
# 在创建表的同时 将 select查询到的数据 插入到创建的表当中。
create table goods_brands(
    id int unsigned primary key auto_increment,
    name varchar(100)
)
select brand_name as name from goods group by brand_name;
# 注意点,使用  create table xxx() ...select ...... 插入数据的时候,
# select 后面的字段 要和 创建的表中的字段名一致,一致的时候,才会将数据插入到指定的字段中
# 如果字段不一致,会在表中创建一个新的列,存储查询出来的数据
# drop table goods_brands;

# 2. 将goods表中的brand_name 改为 goods_brands表中 id
update goods g join goods_brands gb on g.brand_name = gb.name set g.brand_name=gb.id;

# 3. 修改表结构, 将 goods表中的 brand_name 改为 brand_id
alter table goods change brand_name brand_id int unsigned;

2.pymysql模块

帮助我们在python代码中去对mysql数据库中的数据实现增删改查操作。

2.1 pymysql的使用步骤

        

  • 导包

  • 创建连接对象(建立和mysql数据库服务的连接)

  • 创建一个游标对象(这个游标对象就是专门去执行sql语句的对象)

  • 使用游标对象执行sql语句(增删改查)

  • 关闭游标对象

  • 关闭连接对象

pysql查询

# 导包
from pymysql import connect
# 创建连接对象
conn = connect(host='127.0.0.1',port=3306,database='jing_dong',user='root',password='123456',charset='utf8')
# 创建游标对象
cur = conn.cursor()

# 执行sql
#  调用execute 返回值是在执行这条sql时受影响的行数。
num = cur.execute('select * from goods where price > 3000 ')
# print(num)
# print(cur.fetchmany(5))    fetchmany 返回指定条数的数据
# print(cur.fetchall())   fetchall 返回查询的所有结果,返回一个元组
# print(cur.fetchone())  fetchone 获取的是查询结果的的单个数据 返回一个元组,元组中的元素就是这条数据的列值
res =cur.fetchone()
print(res)
# 关闭游标对象和连接对象
cur.close()
conn.close()

2.1 pymysql 增删改

1.数据提交和数据回滚

  • 数据提交commit

数据库中的基本操作: 增删改查. 上一个章节中我们知道如何完成对数据库中数据的获取其实也就是, 比如获取一条数据或者获取所有数据等. 

注意:查数据, 并不会对原有数据库中的数据造成影响. 而增删改这三个操作都会对原有数据库中的数据造成影响. 也就说查数据不会修改原有数据空中的数据, 而增删改会修改原有数据库中的数据.

当对原有数据库中数据有修改时需要使用:

# commit()提交数据到数据库
# 这里可以理解为 数据库询问是否确定修改数据 然后commit()就是确定修改的意思
conn.commit()
  • 数据回滚rollback()

当我们在使用pymysql对数据进行响应的操作时, 会有可能会有一些错误操作, 这是如果想要数据返回到最原始的状态可以使用数据回滚操作

注意:数据回滚是需要在 commit() 之前才有效的, 也就是说数据还没有确定修改这时候使用数据回滚才是有效的

# 回滚数据到什么都没做的原始状态 即撤销刚刚所有的修改操作
conn.rollback()

说白了,就是修改数据的时候,数据不会立即保持到mysql服务器中,而是在缓存中。commit就是确认将缓存中修改的数据保持到mysql服务器中,rollback就是撤销修改。

2.pymysql的增删改操作

# 演示pymysql的增删改操作
import pymysql

# 创建连接对象
conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='root',
    password='mysql',
    charset='utf8'
)

# 连接数据库的时候 可以去指定要操作的数据库名字。 切换数据库: use 数据库名;
conn.select_db('jing_dong')

# 创建游标对象
cursor = conn.cursor()

# sql_str = "show tables;"
# cursor.execute(sql_str)

# 1. 增加数据
# sql_str = "insert into test(name) values('小明');"
# cursor.execute(sql_str)

# 2. 删除数据
# sql_str = 'delete from test where id=1;'
# cursor.execute(sql_str)

# 3. 修改数据
sql_str = "update test set name='小明明' where id=5;"
cursor.execute(sql_str)

# 在使用pymysql对数据进行增删改操作的时候,需要我们手动的提交事务、
conn.commit()

# 获取执行结果
# print(cursor.fetchall())

cursor.close()
conn.close()

# 在使用pymysql进行对数据的 增删改的时候,操作完毕之后,记得 使用连接对象.commit() 对操作的数据进行提交之后才会在表中生效

3.sql注入

1. 什么是SQL注入

  • SQL注入:

    简单说sql注入是一种可以使得数据库中的数据泄露的方式. 如果有一些人有恶意的目的, 可以利用sql注入完成盗取数据.

  • 产生原因:

    后台将用户提交的带有恶意的数据和SQL进行字符串方式的拼接,从而影响了SQL语句的语义,最终产生数据泄露的现象.

               简单的说, 就是利用各种方式提交数据给程序并让这些数据和SQL语句产生结合, 进而让新产生的SQL语句和之前的原始的SQL语句变成不同的意思, 至此就可以利用新产生的SQL语句获取想要的数据了.

  • 防止SQL注入

    SQL语句的参数化可以防止SQL注入的产生. 将SQL语句的所有数据参数存在一个列表中传递给execute函数的第二个参数进行执行, 就是SQL语句参数化.

# 把sql语句需要的参数放到一个列表中
my_list = [xxx,xxx,xxx]
# 把列表作为execute方法的第二个参数传递
cursor.execute(sql,my_list)

2.非安全方式的SQL语句

from pymysql import connect

# 创建Connection连接
conn = connect(host='localhost', port=3306, user='root', password='mysql', database='jing_dong', charset='utf8')

# 获得Cursor对象
cur = conn.cursor()

# 获取用户想要查询的物品名称
find_name = input("请输入物品名称:")

# 非安全方式的sql语句
sql = 'select * from goods where name="%s"' % find_name

# 执行sql语句
count = cur.execute(sql)

# 获取查询的结果
result = cur.fetchall()

# 打印查询的结果
print(result)

# 关闭Cursor对象
cur.close()

# 关闭Connection对象
conn.close()

注意:

在输入商品名称的时候,输入

# 双引号也要输入
" or 1=1 or "

这样就完成了一个简单的注入

# 原始的sql语句
sql = 'select * from goods where name="%s"' % find_name
# 输入 " or 1=1 or "  后的sql语句 
sql = 'select * from goods where name="" or 1=1 or ""'

这里 name= "" or 1=1 or "" 这个条件是一定成立的,因为or是或的意思多个条件只要有一个条件成立整体就成立,而1=1是一定成立的. 这就造成这个sql语句的意思发生里改变.

3.安全方式的SQL语句

from pymysql import connect

# 创建Connection连接
conn = connect(host='localhost', port=3306, user='root', password='mysql', database='jing_dong', charset='utf8')

# 获得Cursor对象
cur = conn.cursor()

# 获取用户想要查询的物品名称
find_name = input("请输入物品名称:")

# sql语句
# 注意: 
# 此处不同于python的字符串格式化,必须全部使用%s占位
# 所有参数所需占位符外不需要加引号
sql = 'select * from goods where name=%s;'

# 安全的方式
# 构造参数列表 
params = [find_name]
# 执行select语句
# 注意:
# 如果要是有多个参数,需要进行参数化
# 那么params = [数值1, 数值2....],此时sql语句中有多个%s即可 
count = cur.execute(sql, params)

# 获取查询的结果
result = cur.fetchall()

# 打印查询的结果
print(result)

# 关闭Cursor对象
cur.close()

# 关闭Connection对象
conn.close()

如果构建的不是参数列表,而是一个字典,那么占位符%s,改成 %()s  括号里面写入字典的键

如下:

her = input('请输入:')
her_dicr = {'name':her}
sql = 'select * from hero where hname=%(name)s'

count = cur.execute(sql,her_dicr)

利用参数化列表就可以完成防止SQL注入

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值