Python中操作MySQL/Oracle

  • 一、Python操作数据库介绍
  • 二、Python操作MySQL
    • 2.1 PySQL模块
      • 2.1.1 安装PyMySQL
    • 2.2 基本使用
    • 2.3 获取最新创建的数据库自增ID
    • 2.4 查询操作
    • 2.5 防止SQL注入
  • 三、数据库连接池
    • 3.1 DBUtils模块
    • 3.2 模式一
    • 3.3 模式二
    • 3.3 加锁
    • 3.4 无锁(报错)
  • 四、数据库连接池结合pymysql使用
  • 五、MySQL中substr()函数的使用
  • 参考资料

一、Python操作数据库介绍

Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:

GadFly
mSQL
MySQL
PostgreSQL
Microsoft SQL Server 2000
Informix
Interbase
Oracle
Sybase …

你可以访问Python数据库接口及API查看详细的支持数据库列表。

不同的数据库你需要下载不同的DB API模块,例如你需要访问Oracle数据库和Mysql数据,你需要下载Oracle和MySQL数据库模块。

DB-API 是一个规范. 它定义了一系列必须的对象和数据库存取方式, 以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口 。

Python的DB-API,为大多数的数据库实现了接口,使用它连接各数据库后,就可以用相同的方式操作各数据库。

Python DB-API使用流程:

  • 引入 API 模块。
  • 获取与数据库的连接。
  • 执行SQL语句和存储过程。
  • 关闭数据库连接。

二、Python操作MySQL

Python操作MySQL主要使用两种方式:

  1. DB模块(原生SQL)
    PyMySQL(支持python2.x/3.x)
    MySQLdb(目前仅支持python2.x)

  2. ORM框架
    SQLAchemy

2.1 PySQL模块

本文主要介绍PyMySQL模块,MySQLdb使用方式类似

2.1.1 安装PyMySQL

笔者的开发环境:Windows 10 Education、Python3.8

PyMySQL是一个Python编写的MySQL驱动程序,让我们可以用Python语言操作MySQL数据库。

pip install PyMySQL

2.2 基本使用

# 1 基本使用pymysql
import pymysql# 创建连接
conn = pymysql.connect(host="127.0.0.1", port=3306, user="root", password="123456", db="springbootdb",charset="utf8mb4")
# 创建游标(查询数据返回的元组格式)
cursor = conn.cursor()# 创建游标(查询数据返回字典格式)
# cursor = conn.cursor(pymysql.cursors.DictCursor)# 1.指定SQL,返回受影响的行数,一次插入一行数据
effect_row1 = cursor.execute("insert into city (province_id, city_name, description) value (61, '渭南', '陕西省渭南市')")# 2. 执行SQL,返回受影响的行数
effect_row2 = cursor.execute("select * from city")# 查询所有数据,返回数据为元组格式
result = cursor.fetchall()# 增删改需要进行commit提交
conn.commit()# 关闭游标
cursor.close()# 关闭连接
conn.close()print(result)

2.3 获取最新创建的数据库自增ID

# 2 获取最新创建的数据自增ID
import pymysqlhost = "127.0.0.1"
port = 3306
user = "root"
password = "123456"
db = "springbootdb"
charset = "utf8mb4"# 创建连接
conn = pymysql.connect(host=host, port=port, user=user, password=password, db=db, charset=charset)# 创建游标(查询数据返回元组格式)
cursor = conn.cursor()# 获取新创建数据自增ID
effect_row = cursor.executemany("insert into city (province_id, city_name, description) values (%s, %s, %s)",[("61", "咸阳1", "陕西省咸阳市"), ("61", "咸阳2", "陕西省咸阳市"), ("61", "咸阳3", "陕西省咸阳市")])# 增删改需要进行commit操作
conn.commit()# 关闭游标
cursor.close()new_id = cursor.lastrowid
print(new_id)

2.4 查询操作

# 3 查询操作
import pymysqlhost = "127.0.0.1"
port = 3306
user = "root"
password = "123456"
db = "springbootdb"
charset = "utf8mb4"# 创建连接
conn = pymysql.connect(host=host, port=port, user=user, password=password, db=db, charset=charset)# 创建游标
cursor = conn.cursor()cursor.execute("select * from city")# 获取第一行数据
row_1 = cursor.fetchone()# 获取前N行数据
row_2 = cursor.fetchmany(3)# 获取所有数据
row_3 = cursor.fetchall()# 关闭游标
cursor.close()# 关闭连接
conn.close()print(row_1)
print(row_2)
print(row_3)

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

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

2.5 防止SQL注入

# 4 防止SQL注入
import pymysqlhost = "127.0.0.1"
port = 3306
user = "root"
password = "123456"
db = "springbootdb"
charset = "utf8mb4"# 创建连接
conn = pymysql.connect(host=host, port=port, user=user, passwd=password, db=db, charset=charset)# 创建游标
cursor = conn.cursor()# 存在SQL注入情况(不要用格式化字符串的方式拼接SQL)
sql = "insert into city(province_id, city_name, description) VALUES (%d,'%s','%s')" % (61, '榆林', '陕西省榆林市')
effect_row = cursor.execute(sql)
print(effect_row)# 正确方式一
# execute函数接受一个元组/列表作为SQL参数,元素个数只能有一个
sql = "insert into city (province_id, city_name, description) values (%s, %s, %s)"
effect_row1 = cursor.executemany(sql, [("61", "榆林", "陕西省榆林市")])
print(effect_row1)# 正确方式二
sql = "insert into city (province_id, city_name, description) VALUES (%(province_id)s,%(city_name)s,%(description)s)"
effect_row2 = cursor.execute(sql, {"province_id": "61", "city_name": "延安", "description": "陕西省延安市"})
print(effect_row2)# 写入多行数据
sql = "insert into city (province_id, city_name, description) values (%s, %s, %s)"
effect_row3 = cursor.executemany(sql, [("61", "榆林1", "陕西省榆林市"), ("61", "榆林2", "陕西省榆林市"), ("61", "榆林3", "陕西省榆林市")])
print(effect_row3)# 提交
conn.commit()# 关闭游标
cursor.close()# 关闭连接
conn.close()

这样,SQL操作就更安全了。如果需要更详细的文档参考PyMySQL文档吧。不过好像这些SQL数据库的实现还不太一样,PyMySQL的参数占位符使用%s这样的C格式化符,而Python自带的sqlite3模块的占位符好像是问号(?)。因此在使用其他数据库的时候还是仔细阅读文档吧。Welcome to PyMySQL’s documentation

三、数据库连接池

上文中的方式存在一个问题,单线程情况下可以满足,程序需要频繁的创建释放连接来完成对数据库的操作,那么,我们的程序/脚本在多线程情况下会引发什么问题呢?此时,我们就需要使用数据库连接池来解决这个问题!

3.1 DBUtils模块

DBUtils是Python的一个用于实现数据库连接池的模块。
此连接池有两种连接模式:

  • 为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程再次使用。当线程终止时,连接才会自动关闭
  • 创建一批连接到连接池,供所有线程共享使用(推荐使用)

3.2 模式一

  • 为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程再次使用。当线程终止时,连接才会自动关闭
from DBUtils.PersistentDB import PersistentDB
import pymysqlPOOL = PersistentDB(creator=pymysql,  # 使用链接数据库的模块maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]ping=0,# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = alwayscloseable=False,# 如果为False时, conn.close() 实际上被忽略,供下次使用,再线程关闭时,才会自动关闭链接。如果为True时, conn.close()则关闭链接,那么再次调用pool.connection时就会报错,因为已经真的关闭了连接(pool.steady_connection()可以获取一个新的链接)threadlocal=None,  # 本线程独享值得对象,用于保存链接对象,如果链接对象被重置host='127.0.0.1',port=3306,user='zff',password='zff123',database='zff',charset='utf8',
)def func():conn = POOL.connection(shareable=False)cursor = conn.cursor()cursor.execute('select * from USER')result = cursor.fetchall()cursor.close()conn.close()return resultresult = func()
print(result)

3.3 模式二

  • 创建一批连接到连接池,供所有线程共享使用(推荐使用)
import time
import pymysql
import threading
from DBUtils.PooledDB import PooledDB, SharedDBConnectionPOOL = PooledDB(creator=pymysql,  # 使用链接数据库的模块maxconnections=6,  # 连接池允许的最大连接数,0和None表示不限制连接数mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建maxcached=5,  # 链接池中最多闲置的链接,0和None不限制maxshared=3,# 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]ping=0,# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = alwayshost='127.0.0.1',port=3306,user='zff',password='zff123',database='zff',charset='utf8'
)def func():# 检测当前正在运行连接数的是否小于最大链接数,如果不小于则:等待或报raise TooManyConnections异常# 否则# 则优先去初始化时创建的链接中获取链接 SteadyDBConnection。# 然后将SteadyDBConnection对象封装到PooledDedicatedDBConnection中并返回。# 如果最开始创建的链接没有链接,则去创建一个SteadyDBConnection对象,再封装到PooledDedicatedDBConnection中并返回。# 一旦关闭链接后,连接就返回到连接池让后续线程继续使用。conn = POOL.connection()# print('连接被拿走了', conn._con)# print('池子里目前有', POOL._idle_cache, '\r\n')cursor = conn.cursor()cursor.execute('select * from USER')result = cursor.fetchall()conn.close()return resultresult = func()
print(result)

由于pymysql、MySQLdb等threadsafety值为1,所以该模式连接池中的线程会被所有线程共享,因此是线程安全的。如果没有连接池,使用pymysql来连接数据库时,单线程应用完全没有问题,但如果涉及到多线程应用那么就需要加锁,一旦加锁那么连接势必就会排队等待,当请求比较多时,性能就会降低了。

3.3 加锁

import pymysql
import threading
from threading import RLockLOCK = RLock()
CONN = pymysql.connect(host='127.0.0.1',port=3306,user='zff',password='zff123',database='zff',charset='utf8')def task(arg):with LOCK:cursor = CONN.cursor()cursor.execute('select * from USER ')result = cursor.fetchall()cursor.close()print(result)for i in range(10):t = threading.Thread(target=task, args=(i,))t.start()

3.4 无锁(报错)

import pymysql
import threadingCONN = pymysql.connect(host='127.0.0.1',port=3306,user='zff',password='zff123',database='zff',charset='utf8')def task(arg):cursor = CONN.cursor()cursor.execute('select * from USER ')# cursor.execute('select sleep(10)')result = cursor.fetchall()cursor.close()print(result)for i in range(10):t = threading.Thread(target=task, args=(i,))t.start()

此时可以在数据库中查看连接情况: show status like ‘Threads%’;

四、数据库连接池结合pymysql使用

import pymysql
import threading
from DBUtils.PooledDB import PooledDB, SharedDBConnection
POOL = PooledDB(creator=pymysql,  # 使用链接数据库的模块maxconnections=20,  # 连接池允许的最大连接数,0和None表示不限制连接数mincached=2,  # 初始化时,链接池中至少创建的空闲的链接,0表示不创建maxcached=5,  # 链接池中最多闲置的链接,0和None不限制#maxshared=3,  # 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。blocking=True,  # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错maxusage=None,  # 一个链接最多被重复使用的次数,None表示无限制setsession=[],  # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]ping=0,# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = alwayshost='192.168.11.38',port=3306,user='root',passwd='apNXgF6RDitFtDQx',db='m2day03db',charset='utf8'
)def connect():# 创建连接# conn = pymysql.connect(host='192.168.11.38', port=3306, user='root', passwd='apNXgF6RDitFtDQx', db='m2day03db')conn = POOL.connection()# 创建游标cursor = conn.cursor(pymysql.cursors.DictCursor)return conn,cursordef close(conn,cursor):# 关闭游标cursor.close()# 关闭连接conn.close()def fetch_one(sql,args):conn,cursor = connect()# 执行SQL,并返回收影响行数effect_row = cursor.execute(sql,args)result = cursor.fetchone()close(conn,cursor)return resultdef fetch_all(sql,args):conn, cursor = connect()# 执行SQL,并返回收影响行数cursor.execute(sql,args)result = cursor.fetchall()close(conn, cursor)return resultdef insert(sql,args):"""创建数据:param sql: 含有占位符的SQL:return:"""conn, cursor = connect()# 执行SQL,并返回收影响行数effect_row = cursor.execute(sql,args)conn.commit()close(conn, cursor)def delete(sql,args):"""创建数据:param sql: 含有占位符的SQL:return:"""conn, cursor = connect()# 执行SQL,并返回收影响行数effect_row = cursor.execute(sql,args)conn.commit()close(conn, cursor)return effect_rowdef update(sql,args):conn, cursor = connect()# 执行SQL,并返回收影响行数effect_row = cursor.execute(sql, args)conn.commit()close(conn, cursor)return effect_row

五、MySQL中substr()函数的使用

对于JavaScript的substring() 方法或者String的subString()方法,相信很多人都有用过,最近因为工作的需要,需要在sql中对字段进行切割。SUBSTR函数是用来截取数据库某一列字段中的一部分,在各个数据库的函数名称不一样。

    MySQL: SUBSTR( ), SUBSTRING( ) Oracle: SUBSTR( ) SQL Server: SUBSTRING( ) ;

常用的方式是:

SBUSTR(str,pos); 从pos开始的位置,一直截取到最后。

还有一种比较常用的是:

SUBSTR(str,pos,len);从pos开始的位置,截取len个字符(空白也算字符)。

注:
mysql中的substr()函数和hibernate的substr()参数都一样,就是含义有所不同。
mysql中的start是从1开始的,而hibernate中的start是从0开始的。

举个栗子

查询到的原始数据格式为:

select a.visitdate
from src_his_mz_master_info a;


SUBSTR(str,pos,len);
从pos开始的位置,截取len个字符(空白也算字符)。

select substr(a.visitdate,1,4)
from src_his_mz_master_info a;


SBUSTR(str,pos);
从pos开始的位置,一直截取到最后。

select substr(a.visitdate,6)
from src_his_mz_master_info a;

参考资料

  1. https://mp.weixin.qq.com/s/vXAbJ9KcSDB0CAMWBL0IJg
  2. https://mp.weixin.qq.com/s/8V2puF-QbG6gVI6MIDDFdg
  3. https://mp.weixin.qq.com/s/LAaGDQd-AX2jGkgUjlufLg

Python中操作MySQL/Oracle相关推荐

  1. python中的pymysql_(转)Python中操作mysql的pymysql模块详解

    原文:https://www.cnblogs.com/wt11/p/6141225.html https://shockerli.net/post/python3-pymysql/----Python ...

  2. Python中操作mysql的pymysql模块详解

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

  3. 二十三、python中操作MySQL步骤

    python中操作mysql步骤 1.引入模块 在py文件中引入pymysql模块 from pymysql import * 2.connection对象 用于建立与数据库的连接 创建对象:调用co ...

  4. Python中操作mysql知识(一)

    Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口. Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库: ...

  5. Python 中操作 MySQL 步骤

    1.引入模块 在py文件中引入pymysql模块 from pymysql import * 2.Connection 对象 用于建立与数据库的连接 创建对象:调用connect()方法 conn=c ...

  6. python中操作mysql数据库CRUD(增、删、改、查)

    一.插入操作 #coding:utf8 import pymysql.cursors #连接数据库 conn=pymysql.Connect(user="root",passwor ...

  7. python的mysql模块_Python中操作mysql的pymysql模块详解

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

  8. python propresql mysql_Python中操作mysql的pymysql模块详解

    PyMySQL是一个Python编写的MySQL驱动程序,让我们可以用Python语言操作MySQL数据库. 首先,使用pip安装PyMySQL. pip install PyMySQL 使用PyMy ...

  9. Win10+Python+Django+Nginx+MySQL开发教程及实例(2)——Python连通操作MySQL

    Win10+Python+Django+Nginx+MySQL开发教程及实例 PaulTsao 本系列教程共有四篇内容: 第一篇: 开发环境搭建 第二篇:用Python连通操作MySQL 第三篇:用N ...

最新文章

  1. Linux如何打开执行脚本
  2. UIWebView相关应用
  3. svm解决兵王问题_机器学习: svm
  4. Oracle触发器2-DML触发器
  5. 玩嗨的 2 亿快手“老铁”和幕后的极致视觉算法
  6. 2008年9月三级网络技术考试试卷 参考答案1
  7. 许晴×××汤的营养价值
  8. scala的函数化编程
  9. zabbix client安装配置执行
  10. win10计算机丢失msvcr,Win10系统打开软件提示丢失msvcr110.dll如何解决
  11. WINPE启动盘的制作
  12. 设计模式之 Factory Mode 工厂模式:Swift 实现
  13. win10计算机睡眠怎么设置密码,怎么取消win10睡眠模式唤醒密码 Win10睡眠模式怎么设置取消唤醒密码...
  14. 2021-01-22
  15. kettle4.1 连接 mysql8 库异常:org.gjt.mm.mysql.Driver
  16. python提取excel前十行生成图_Python读取Excel数据生成图表 v2.0
  17. linux aeon gcc,在rosettaCM中,一些操作所需要的linux命令
  18. 自定义配置数据源 DataSource
  19. [linux] bash_profile 编辑(i)/退出编辑(esc)/退出(:wq)
  20. 在内容创作领域,为什么李筱懿如此成功?

热门文章

  1. git 如何同步本地tag与远程tag
  2. 2019.02.07 bzoj4316: 小C的独立集(仙人掌+树形dp)
  3. 树莓派1 安装使用 ZeroTier
  4. HTTP简介,http是一个属于应用层的面向对象的协议
  5. Spark SQL之External DataSource外部数据源(二)源代码分析
  6. AC日记——凌乱的yyy 洛谷 P1803
  7. VS2013 UML 如何复制文件
  8. angularjs 导出excel php,AngularJS 导出Excel指令
  9. java库net2.0下载_.NET Framework各版本独立下载.NET Framework 3.5下载.NET Framework 2.0下载...
  10. softmax函数_干货 | 浅谈 Softmax 函数