参考文档Python-PyMysql详解
参考文档使用pandas操作MySQL数据库
1 pymysql操作mysql
PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库。
PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。
pip install PyMySQL
1.1 连接数据库
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# 使用execute()方法执行SQL查询,获取数据库版本
cur.execute("SELECT VERSION()")
# 使用fetchone()方法获取单条数据.
data = cur.fetchone()
print(data)
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
输出如下:(‘8.0.19’,)。
1.2 创建数据表
如果数据库连接存在我们可以使用execute()方法来为数据库创建表,如下所示创建表EMPLOYEE:
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# 使用预处理语句创建表
sql_create = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )"""
#执行sql语句
cur.execute(sql_create)
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.3 插入操作
1.3.1 普通的插入
以下实例使用执行SQL INSERT语句向表EMPLOYEE插入记录:
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# SQL 插入语句
sql_insert = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
try:
# 执行sql语句
cur.execute(sql_insert)
# 提交到数据库执行
con.commit()
except:
# 如果发生错误则回滚
con.rollback()
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.3.2 变量传值
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
first_name='lucy'
last_name='kalt'
age=22
sex='M'
income=1800
# SQL 插入语句
sql_insert = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('{}','{}',{},'{}',{})""".format(first_name, last_name, age, sex, income)
print(sql_insert)
try:
# 执行sql语句
cur.execute(sql_insert)
# 执行sql语句
con.commit()
except:
# 发生错误时回滚
con.rollback()
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.3.3 批量写入
通过python向mysql插入大量数据时,可以有两种方法:
1、for + cursor.execute(sql),最后集中提交commit()。
2、cursor.executemany(sql,list)。
两种方法效率上和功能上有一定差异。26万条数据,使用第一种方法需要约1.5小时,使用第二种方法只需要10几秒。
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# 必须是元组列表的格式
list_1 = [('lily','kalt',22,'M',1900),('jim','kalt',22,'M',2000)]
# SQL 插入语句
# 注意,这里的%s不需要加引号,使用execute需要加引号。
# 另外,executemany 在执行过程中能够将python的None转为sql的null,这一点很方便。
sql_1 = """insert into EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME) values(%s,%s,%s,%s,%s)"""
try:
# 执行sql语句
cur.executemany(sql_1,list_1)
# 执行sql语句
con.commit()
except:
# 发生错误时回滚
con.rollback()
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.4 查询操作
Python查询Mysql使用fetchone()方法获取单条数据, 使用fetchall()方法获取多条数据。
fetchone(): 该方法获取下一个查询结果集。结果集是一个对象。
fetchall(): 接收全部的返回结果行.
rowcount: 这是一个只读属性,并返回执行execute()方法后影响的行数。
1.4.1 返回元组
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# SQL 查询语句
sql_select = "SELECT * FROM EMPLOYEE \
WHERE INCOME > %s" % (1000)
try:
# 执行SQL语句
cur.execute(sql_select)
# 获取所有记录列表,以元组来存储
results = cur.fetchall()
print(results)
# 遍历元组存值
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# 打印结果
print("fname={},lname={},age={},sex={},income={}".format(fname, lname, age, sex, income))
except:
print("错误:没有查找到数据")
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.4.2 转为DataFrame
返回的results可以直接转换为DataFrame。
import pandas as pd
# 指定好列名
df = pd.DataFrame(results,columns=["fname","lname","age","sex","income"])
print(df)
1.5 更新操作
更新操作用于更新数据表的数据,以下实例将表中SEX为 ‘M’ 的AGE字段递增 1:
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# SQL 更新语句
sql_update = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '{}'".format('M')
try:
# 执行SQL语句
cur.execute(sql_update)
# 提交到数据库执行
con.commit()
except:
# 发生错误时回滚
con.rollback()
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.6 删除操作
删除操作用于删除数据表中的数据,以下实例演示了删除数据表 EMPLOYEE 中 AGE 大于 22 的所有数据:
import pymysql
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
# 创建连接
con = pymysql.Connect(host=config.HOST,
port=config.PORT,
user=config.USERNAME,
passwd=config.PASSWORD,
db=config.DBNAME)
# 使用cursor()方法创建一个游标对象cursor
cur = con.cursor()
# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > {}".format(22)
try:
# 执行SQL语句
cur.execute(sql)
# 提交修改
con.commit()
except:
# 发生错误时回滚
con.rollback()
# 关闭不使用的游标对象
cur.close()
# 关闭数据库连接
con.close()
1.7 执行事务
事务机制可以确保数据一致性。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
(1)原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
(2)一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
(3)隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
(4)持久性(durability)。持续性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
Python DB API 2.0 的事务提供了两个方法 commit 和 rollback。
# SQL删除记录语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > %s" % (20)
try:
# 执行SQL语句
cur.execute(sql)
# 向数据库提交
con.commit()
except:
# 发生错误时回滚
con.rollback()
对于支持事务的数据库, 在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。commit()方法提交游标的所有更新操作,rollback()方法回滚当前游标的所有操作。每一个方法都开始了一个新的事务。
1.8 自动提交
在创建连接的时候,增加参数 autocommit = 1 ,当发生update等操作时,会实时更新到数据库内。否则要通过 conn.commit() 来提交到数据库进行具体操作。
如果没有设置自动提交,也没有手动提交,当进行插入或更新等操作时,只在本地客户端能看到更新,在其他客户端或数据库内,数据无变化。
# 实时操作,适合随时少量、频繁的更新
import pymysql
con = pymysql.connect(
host='XXX.XXX.XXX.XXX',
user='XXXXX',
password='XXXXX',
db='XXXXX',
port=3306,
charset='utf8',
autocommit = 1 ,
)
# 集中大批量操作数据
import pymysql
con = pymysql.connect(
host='XXX.XXX.XXX.XXX',
user='XXXXX',
password='XXXXX',
db='XXXXX',
port=3306,
charset='utf8',
)
SQl相关操作略
con.commit() # 提交
2 pandas操作mysql
使用PyMySQL包获取的数据为元组或者字典格式,如果要做进一步的处理,还需要转换成pandas的DataFrame格式,比较麻烦。而直接用pandas的read_sql_query()函数可以直接得到DataFrame格式的数据,而且同样可以对表进行增删改查的操作。
2.1 连接数据库
import pymysql
import pandas as pd
import sqlalchemy
# (1)数据库信息
class config(object):
HOST = "localhost"
PORT = 3306
USERNAME = "root"
PASSWORD = "xxxx"
DBNAME = "test"
#创建数据库的连接引擎
# 例如'mysql+pymysql://root:4869@127.0.0.1:3306/question?charset=utf8'需要结合import pymysql
# 例如'mysql://用户名:密码@主机名或IP地址:端口/库名称?charset=utf8'需要结合import MySQLdb
con_str = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(config.USERNAME,config.PASSWORD,config.HOST,config.PORT,config.DBNAME)
# con_str = 'mysql://{}:{}@{}:{}/{}?charset=utf8'.format(config.USERNAME,config.PASSWORD,config.HOST,config.PORT,config.DBNAME)
engine=sqlalchemy.create_engine(con_str )
2.2 读取数据
sql可以是表名称,读取该表所有数据存为dataframe, sql也可以是一句可以执行的sql语句,比如select语句。
2.2.1 pd.read_sql()
(1)表名称
df = pd.read_sql(sql='employee', con=engine)
print(df)
(2)执行sql语句
sql_str = "select * from employee"
df1 = pd.read_sql(sql=sql_str, con=engine)
print(df1)
2.2.2 pd.read_sql_query()
只能是sql语句
sql_str = "select * from employee"
df1 = pd.read_sql_query(sql=sql_str, con=engine)
print(df1)
read_sql_query()函数还有一些其他的参数:
coerce:尝试将非字符串及非数值对象转换成浮点数字,默认为True
params:可以是列表、字典、元组,用于存储动态拼接SQL命令的变量
parse_dates:将指定字段解析成日期格式
chunksize:如果不设置,返回的是DataFrame对象
2.3 写入数据
df.to_sql(name='tablename', con=engine, if_exists='append', index=False, chunksize=1000)
(1)name 指定的是目标数据库表
(2)con 与数据库链接的方式,推荐使用sqlalchemy的engine类型
(3)if_exists 当数据库中已经存在数据表时对数据表的操作,有replace替换、append追加,fail则当表存在时提示ValueError
(4)index 对DataFrame的index索引的处理,=True时索引也将作为数据写入数据表
(5)chunsize 整数,一次写入数据时的数据行数量
如果没有表,会自动创建表,其字段类型可能不符合要求,所以还是提前创建。
列名对应表中的字段。