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的Django框架中加载模版的方法
Jul 16 Python
python2.7的编码问题与解决方法
Oct 04 Python
Python实现查找匹配项作处理后再替换回去的方法
Jun 10 Python
python 表达式和语句及for、while循环练习实例
Jul 07 Python
pyspark.sql.DataFrame与pandas.DataFrame之间的相互转换实例
Aug 02 Python
python networkx 根据图的权重画图实现
Jul 10 Python
python求加权平均值的实例(附纯python写法)
Aug 22 Python
python双端队列原理、实现与使用方法分析
Nov 27 Python
Tensorflow不支持AVX2指令集的解决方法
Feb 03 Python
Python使用xpath实现图片爬取
Sep 16 Python
python 输入字符串生成所有有效的IP地址(LeetCode 93号题)
Oct 15 Python
python实现web邮箱扫描的示例(附源码)
Mar 30 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
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
在PHP中检查PHP文件是否有语法错误的方法
2009/12/23 PHP
PHP编程中尝试程序并发的几种方式总结
2016/03/21 PHP
php ucwords() 函数将字符串中每个单词的首字符转换为大写(实现代码)
2016/05/12 PHP
php中各种定义变量的方法小结
2017/10/18 PHP
JS效率个人经验谈(8-15更新),加入range技巧
2007/01/09 Javascript
js正确获取元素样式详解
2009/08/07 Javascript
jquery scrollTop方法根据滚动像素显示隐藏顶部导航条
2013/05/27 Javascript
使用原生js实现页面蒙灰(mask)效果示例代码
2014/06/20 Javascript
js全选按钮的实现方法
2015/11/17 Javascript
Treegrid的动态加载实例代码
2016/04/29 Javascript
详解Js模板引擎(TrimPath)
2016/11/22 Javascript
jquery实现异步加载图片(懒加载图片一种方式)
2017/04/24 jQuery
深入理解Vuex 模块化(module)
2017/09/26 Javascript
使用watch监听路由变化和watch监听对象的实例
2018/02/24 Javascript
angularjs实现对表单输入改变的监控(ng-change和watch两种方式)
2018/08/29 Javascript
Vue组件间通信 Vuex的用法解析
2019/08/05 Javascript
微信小程序事件流原理解析
2019/11/27 Javascript
Vue父组件监听子组件生命周期
2020/09/03 Javascript
vue3.0封装轮播图组件的步骤
2021/03/04 Vue.js
[56:14]Fnatic vs OG 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
用Python中的wxPython实现最基本的浏览器功能
2015/04/14 Python
简单谈谈Python的pycurl模块
2018/04/07 Python
TensorFlow利用saver保存和提取参数的实例
2018/07/26 Python
在python中实现将一张图片剪切成四份的方法
2018/12/05 Python
Django的ListView超详细用法(含分页paginate)
2020/05/21 Python
Python Opencv实现单目标检测的示例代码
2020/09/08 Python
德国箱包网上商店:koffer24.de
2016/07/27 全球购物
印度最好的在线药品订购网站:PharmEasy
2018/11/30 全球购物
德国家具、照明、家居用品网上商店:Wayfair.de
2020/02/13 全球购物
敬老院活动总结
2014/04/28 职场文书
雨花台导游词
2015/02/06 职场文书
同学聚会开幕词
2019/04/02 职场文书
话题作文之自信作文
2019/11/15 职场文书
MySQL 数据类型详情
2021/11/11 MySQL
mysql数据库如何转移到oracle
2022/12/24 MySQL