Python中操作mysql的pymysql模块详解


Posted in Python onSeptember 13, 2016

前言

pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb几乎相同。但目前pymysql支持python3.x而后者不支持3.x版本。

本文测试python版本:2.7.11。mysql版本:5.6.24

一、安装

pip3 install pymysql

二、使用操作

1、执行SQL

#!/usr/bin/env pytho
# -*- coding:utf-8 -*-
import pymysql
 
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1', charset='utf8')
# 创建游标
cursor = conn.cursor()
 
# 执行SQL,并返回收影响行数
effect_row = cursor.execute("select * from tb7")
 
# 执行SQL,并返回受影响行数
#effect_row = cursor.execute("update tb7 set pass = '123' where nid = %s", (11,))
 
# 执行SQL,并返回受影响行数,执行多次
#effect_row = cursor.executemany("insert into tb7(user,pass,licnese)values(%s,%s,%s)", [("u1","u1pass","11111"),("u2","u2pass","22222")])
 
 
# 提交,不然无法保存新建或者修改的数据
conn.commit()
 
# 关闭游标
cursor.close()
# 关闭连接
conn.close()

注意:存在中文的时候,连接需要添加charset='utf8',否则中文显示乱码。

2、获取查询数据

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()
cursor.execute("select * from tb7")

# 获取剩余结果的第一行数据
row_1 = cursor.fetchone()
print row_1
# 获取剩余结果前n行数据
# row_2 = cursor.fetchmany(3)

# 获取剩余结果所有数据
# row_3 = cursor.fetchall()

conn.commit()
cursor.close()
conn.close()

3、获取新创建数据自增ID

可以获取到最新自增的ID,也就是最后插入的一条数据ID

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()
effect_row = cursor.executemany("insert into tb7(user,pass,licnese)values(%s,%s,%s)", [("u3","u3pass","11113"),("u4","u4pass","22224")])
conn.commit()
cursor.close()
conn.close()
#获取自增id
new_id = cursor.lastrowid      
print new_id

4、移动游标

操作都是靠游标,那对游标的控制也是必须的

注:在fetch数据时按照顺序进行,可以使用cursor.scroll(num,mode)来移动游标位置,如:

cursor.scroll(1,mode='relative') # 相对当前位置移动
cursor.scroll(2,mode='absolute') # 相对绝对位置移动

 

5、fetch数据类型

关于默认获取的数据是元祖类型,如果想要或者字典类型的数据,即:

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
#游标设置为字典类型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
cursor.execute("select * from tb7")

row_1 = cursor.fetchone()
print row_1#{u'licnese': 213, u'user': '123', u'nid': 10, u'pass': '213'}

conn.commit()
cursor.close()
conn.close()

6、调用存储过程

a、调用无参存储过程

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
#游标设置为字典类型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
#无参数存储过程
cursor.callproc('p2')  #等价于cursor.execute("call p2()")

row_1 = cursor.fetchone()
print row_1


conn.commit()
cursor.close()
conn.close()

b、调用有参存储过程

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)

cursor.callproc('p1', args=(1, 22, 3, 4))
#获取执行完存储的参数,参数@开头
cursor.execute("select @p1,@_p1_1,@_p1_2,@_p1_3")  #{u'@_p1_1': 22, u'@p1': None, u'@_p1_2': 103, u'@_p1_3': 24}
row_1 = cursor.fetchone()
print row_1


conn.commit()
cursor.close()
conn.close()

三、关于pymysql防注入

 1、字符串拼接查询,造成注入

正常查询语句:

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()
user="u1"
passwd="u1pass"
#正常构造语句的情况
sql="select user,pass from tb7 where user='%s' and pass='%s'" % (user,passwd)
#sql=select user,pass from tb7 where user='u1' and pass='u1pass'
row_count=cursor.execute(sql) row_1 = cursor.fetchone()
print row_count,row_1

conn.commit()
cursor.close()
conn.close()

构造注入语句:

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()

user="u1' or '1'-- "
passwd="u1pass"
sql="select user,pass from tb7 where user='%s' and pass='%s'" % (user,passwd)

#拼接语句被构造成下面这样,永真条件,此时就注入成功了。因此要避免这种情况需使用pymysql提供的参数化查询。
#select user,pass from tb7 where user='u1' or '1'-- ' and pass='u1pass'

row_count=cursor.execute(sql)
row_1 = cursor.fetchone()
print row_count,row_1


conn.commit()
cursor.close()
conn.close()

 

 2、避免注入,使用pymysql提供的参数化语句

正常参数化查询

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"

import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()
user="u1"
passwd="u1pass"
#执行参数化查询
row_count=cursor.execute("select user,pass from tb7 where user=%s and pass=%s",(user,passwd))
row_1 = cursor.fetchone()
print row_count,row_1

conn.commit()
cursor.close()
conn.close()

构造注入,参数化查询注入失败。

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()

user="u1' or '1'-- "
passwd="u1pass"
#执行参数化查询
row_count=cursor.execute("select user,pass from tb7 where user=%s and pass=%s",(user,passwd))
#内部执行参数化生成的SQL语句,对特殊字符进行了加\转义,避免注入语句生成。
# sql=cursor.mogrify("select user,pass from tb7 where user=%s and pass=%s",(user,passwd))
# print sql
#select user,pass from tb7 where user='u1\' or \'1\'-- ' and pass='u1pass'被转义的语句。

row_1 = cursor.fetchone()
print row_count,row_1

conn.commit()
cursor.close()
conn.close()

结论:excute执行SQL语句的时候,必须使用参数化的方式,否则必然产生SQL注入漏洞。

3、使用存mysql储过程动态执行SQL防注入

使用MYSQL存储过程自动提供防注入,动态传入SQL到存储过程执行语句。

delimiter \\
DROP PROCEDURE IF EXISTS proc_sql \\
CREATE PROCEDURE proc_sql (
  in nid1 INT,
  in nid2 INT,
  in callsql VARCHAR(255)
  )
BEGIN
  set @nid1 = nid1;
  set @nid2 = nid2;
  set @callsql = callsql;
    PREPARE myprod FROM @callsql;
--   PREPARE prod FROM 'select * from tb2 where nid>? and nid<?';  传入的值为字符串,?为占位符
--   用@p1,和@p2填充占位符
    EXECUTE myprod USING @nid1,@nid2;
  DEALLOCATE prepare myprod;

END\\
delimiter ;
set @nid1=12;
set @nid2=15;
set @callsql = 'select * from tb7 where nid>? and nid<?';
CALL proc_sql(@nid1,@nid2,@callsql)

pymsql中调用

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"
import pymysql

conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1')
cursor = conn.cursor()
mysql="select * from tb7 where nid>? and nid<?"
cursor.callproc('proc_sql', args=(11, 15, mysql))

rows = cursor.fetchall()
print rows #((12, 'u1', 'u1pass', 11111), (13, 'u2', 'u2pass', 22222), (14, 'u3', 'u3pass', 11113))
conn.commit()
cursor.close()
conn.close()

四、使用with简化连接过程

每次都连接关闭很麻烦,使用上下文管理,简化连接过程

#! /usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = "TKQ"

import pymysql
import contextlib
#定义上下文管理器,连接后自动关闭连接
@contextlib.contextmanager
def mysql(host='127.0.0.1', port=3306, user='root', passwd='', db='tkq1',charset='utf8'):
  conn = pymysql.connect(host=host, port=port, user=user, passwd=passwd, db=db, charset=charset)
  cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
  try:
    yield cursor
  finally:
    conn.commit()
    cursor.close()
    conn.close()

# 执行sql
with mysql() as cursor:
  print(cursor)
  row_count = cursor.execute("select * from tb7")
  row_1 = cursor.fetchone()
  print row_count, row_1

总结

以上就是关于Python中pymysql模块的全部内容,希望对大家学习或使用python能有一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
python中assert用法实例分析
Apr 30 Python
Python 3.x读写csv文件中数字的方法示例
Aug 29 Python
轻松实现TensorFlow微信跳一跳的AI
Jan 05 Python
python2.7 json 转换日期的处理的示例
Mar 07 Python
python3 判断列表是一个空列表的方法
May 04 Python
python  文件的基本操作 菜中菜功能的实例代码
Jul 17 Python
python 公共方法汇总解析
Sep 16 Python
TensorFlow2.0矩阵与向量的加减乘实例
Feb 07 Python
Python 列表中的修改、添加和删除元素的实现
Jun 11 Python
Python 使用生成器代替线程的方法
Aug 04 Python
Python字符串查找基本操作代码案例
Oct 27 Python
Python操作CSV格式文件的方法大全
Jul 15 Python
python常用函数详解
Sep 13 #Python
python如何查看系统网络流量的信息
Sep 12 #Python
Python爬取三国演义的实现方法
Sep 12 #Python
python 读写、创建 文件的方法(必看)
Sep 12 #Python
Python读写Json涉及到中文的处理方法
Sep 12 #Python
详细介绍Python的鸭子类型
Sep 12 #Python
Python 读写文件和file对象的方法(推荐)
Sep 12 #Python
You might like
PHP Pear 安装及使用
2009/03/19 PHP
解析strtr函数的效率问题
2013/06/26 PHP
php中smarty模板条件判断用法实例
2015/06/11 PHP
给WordPress的编辑后台添加提示框的代码实例分享
2015/12/25 PHP
PHP获取当前系统时间的方法小结
2018/10/03 PHP
PHP内部实现打乱字符串顺序函数str_shuffle的方法
2019/02/14 PHP
PHP二维数组分页2种实现方法解析
2020/07/09 PHP
BOOM vs RR BO5 第四场 2.14
2021/03/10 DOTA
javascript onkeydown,onkeyup,onkeypress,onclick,ondblclick
2009/02/04 Javascript
比较简单的异步加载JS文件的代码
2009/07/18 Javascript
Javascript Math ceil()、floor()、round()三个函数的区别
2010/03/09 Javascript
从重置input file标签中看jQuery的 .val() 和 .attr(“value”) 区别
2016/06/12 Javascript
微信小程序中单位rpx和rem的使用
2016/12/06 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
2017/03/07 Javascript
Kindeditor单独调用单图上传增加预览功能的实例
2017/07/31 Javascript
JS分页的实现(同步与异步)
2017/09/16 Javascript
Vue-Access-Control 前端用户权限控制解决方案
2017/12/01 Javascript
vue实现pdf导出解决生成canvas模糊等问题(推荐)
2018/10/18 Javascript
vue 修改 data 数据问题并实时显示操作
2020/09/07 Javascript
Openlayers实现测量功能
2020/09/25 Javascript
python 简单搭建阻塞式单进程,多进程,多线程服务的实例
2017/11/01 Python
python Pandas如何对数据集随机抽样
2019/07/29 Python
css3 border-radius属性详解
2017/07/05 HTML / CSS
Gucci法国官方网站:意大利奢侈品牌
2018/07/25 全球购物
美国在线家居装饰店:Belle&June
2018/10/24 全球购物
解释i节点在文件系统中的作用
2013/11/26 面试题
计算机操作自荐信
2013/12/07 职场文书
红色旅游心得体会
2014/09/03 职场文书
党员倡议书
2015/01/19 职场文书
办公室主任个人总结
2015/02/28 职场文书
开会通知短信大全
2015/04/20 职场文书
2015年环卫工作总结
2015/04/28 职场文书
2016会计专业自荐信范文
2016/01/28 职场文书
Python的flask接收前台的ajax的post数据和get数据的方法
2021/04/12 Python
基于flask实现五子棋小游戏
2021/05/25 Python
MySQL主从切换的超详细步骤
2022/06/28 MySQL