通过Python连接到MySQL数据库
如何将你的Python笔记本连接到MySQL数据库
通常情况下,数据科学家或分析师必须访问数据库,例如用于特定的分析。通常情况下,这些数据库是MySQL数据库,这里你可以使用MySQL连接器从Jupyter笔记本访问MySQL数据库。
代码块
https://pypi.org/project/mysql-connector-python/
https://dev.mysql.com/doc/connector-python/en/
第一步是通过!"pip安装 "命令来安装连接器。
pip install mysql-connector-python
之后,你就可以使用该库并连接到数据库了。
导入连接器
输入mysql.connector
连接到数据库
#Import the Connector
import mysql.connector
# Connecting to the database
conn = mysql.connector.connect(user = ‘username’,host = ‘localhost’,database = ‘database_name’)
然后在游标对象的帮助下,你可以查询表。
初始化一个游标对象
cursorObject = dataBase.cursor()
选择查询
query = "SELECT NAME, FORNAME FROM CUSTOMER"
cursorObject.execute(query)
result = cursorObject.fetchall()
从这里开始,你可以使用结果进行数据准备和聚合。最后但并非最不重要的是--完成后一定要断开与服务器的连接。
与服务器断开连接
conn.close()
这篇文章给了你一个简短的概述,告诉你如何在MySQL连接器的帮助下通过Python笔记本轻松访问MySQL数据库。除了阅读,你当然还可以执行许多其他的操作,比如。
创建/删除一个表
插入记录
以及更多的操作
如果你想更深入地了解,你可以去官方网站[1]
Python数据库访问 - Python 3 MySQL
Python数据库访问
一个数据库是一个通过列相互关联的表的集合。对于大多数现实世界的项目,数据库是必须的。我们可以使用SQL(结构化查询语言)来创建、访问和操作数据。我们还可以利用规范化来避免数据的冗余。
对于数据库编程,Python支持许多数据库服务器:
MySQL、Oracle、PostgreSQL、SQLite、Sybase、Microsoft SQL Server、mSQL、Microsoft Access,... ...
它还支持数据查询语句、数据定义语言(DDL)和数据操作语言(DML)。Python的标准数据库接口是Python DB-API。为此,我们有MySQL的MySQLdb模块。这与数据库引擎无关;所以我们可以编写Python脚本来访问任何数据库引擎。然而,这与Python 3并不兼容。
因此,在这个Python数据库访问教程中,我们使用PyMySQL模块。
用Python进行数据库编程的优势
使用Python,我们有以下好处。
独立于平台
速度更快,效率更高
携带方便
支持关系型数据库系统
易于迁移和移植数据库应用接口
支持SQL游标
它可以处理开放和关闭的连接
PyMySQL和安装
PyMySQL实现了Python数据库API 2.0。在这个Python数据库教程中,我们将使用它从Python连接到一个MySQL数据库服务器。我们有以下要求来安装PyMySQL------。
a. Python(任何一种)
CPython>=2.6或>=3.3
PyPy>=4.0
IronPython 2.7
遵循此链接了解Python如何重命名文件--单个和多个文件
b. MySQL(任何一种)
MySQL>=4.1
MariaDB>=5.1
要安装它,请在命令提示符下运行以下命令
C:\Users\lifei>pip install PyMySQL
采集PyMySQL
Using cached https://files.pythonhosted.org/packages/2f/be/4310bb405eb83b615cf9bd4501942d9ff000d8b9372ce84e920facbf5c36/PyMySQL-0.9.0-py2.py3-none-any.whl
采集密码学(来自PyMySQL)
Downloading https://files.pythonhosted.org/packages/67/62/67faef32908026e816a74b4b97491f8b9ff393d2951820573599c105cc32/cryptography-2.2.2-cp36-cp36m-win_amd64.whl (1.3MB)
100% |████████████████████████████████| 1.3MB 596kB/s
收集idna>=2.1 (从密码学->PyMySQL)
Downloading https://files.pythonhosted.org/packages/4b/2a/0276479a4b3caeb8a8c1af2f8e4355746a97fab05a372e4a2c6a6b876165/idna-2.7-py2.py3-none-any.whl (58kB)
100% |████████████████████████████████| 61kB 1.3MB/s
收集asn1crypto>=0.21.0 (来自cryptography->PyMySQL)
Using cached https://files.pythonhosted.org/packages/ea/cd/35485615f45f30a510576f1a56d1e0a7ad7bd8ab5ed7cdc600ef7cd06222/asn1crypto-0.24.0-py2.py3-none-any.whl
收集 six>=1.4.1 (从密码学->PyMySQL)
让我们阅读Python Zipfile--Python中Zipfiles的好处、模块、对象
Using cached https://files.pythonhosted.org/packages/67/4b/141a581104b1f6397bfa78ac9d43d8ad29a7ca43ea90a2d863fe3056e86a/six-1.11.0-py2.py3-none-any.whl
收集 cffi>=1.7; platform_python_implementation != "PyPy" (from cryptography->PyMySQL)
Downloading https://files.pythonhosted.org/packages/2f/85/a9184548ad4261916d08a50d9e272bf6f93c54f3735878fbfc9335efd94b/cffi-1.11.5-cp36-cp36m-win_amd64.whl (166kB)
100% |████████████████████████████████| 174kB 568kB/s
收集 pycparser (from cffi>=1.7; platform_python_implementation != "PyPy" ->cryptography->PyMySQL)
Using cached https://files.pythonhosted.org/packages/8c/2d/aad7f16146f4197a11f8e91fb81df177adcc2073d36a17b1491fd09df6ed/pycparser-2.18.tar.gz
安装收集的软件包:idna, asn1crypto, six, pycparser, cffi, cryptography, PyMySQL
运行 setup.py install for pycparser ... done
成功地安装了 PyMySQL-0.9.0 asn1crypto-0.24.0 cffi-1.11.5 cryptography-2.2.2 idna-2.7 pycparser-2.18 six-1.11.0
另外,确保在你的机器上安装一个数据库服务器。在这篇文章中,我们使用MySQL。我们从这里下载它--
dev.mysql.com/downloads/mysql
连接Python数据库
现在你已经安装好了一切,让我们开始连接数据库。让我们先创建一个数据库。
a. 如何创建Python数据库?
以及更多的操作
mysql> create database demo;
Query OK, 1 row affected (0.21 sec)
mysql> use demo;
Database changed
mysql> create user ‘ayushi’@’localhost’ IDENTIFIED BY ‘yourpassword’
-> ;
Query OK, 0 rows affected (0.21 sec)
mysql> grant all on demo.* to ‘ayushi’@’localhost’;
Query OK, 0 rows affected (0.22 sec)
mysql> create table student(fname varchar(20), lname varchar(20), age int, enrolment_no varchar(12));
Query OK, 0 rows affected (0.62 sec)
b. 如何连接Python数据库?
import pymysql
db=pymysql.connect(“localhost”,”ayushi”,”yourpassword”,”demo”) #This saves a connection object into db
cursor=db.cursor()
cursor.execute(“SELECT VERSION()”)
1
print(f”You’re running version {cursor.fetchone()}”)
You’re running version (‘8.0.11’,)
db.close() #Closing the database connection
A cursor is an object that submits different SQL statements to the database server. A cursor returns a result set object.
游标是一个可以向数据库服务器提交不同SQL语句的对象。游标返回一个结果集对象。
让我们了解一下Python工具--Python的4个主要实用工具
如何在Python数据库中创建表?
现在让我们逐一看看所有的操作,从创建一个表开始。
import pymysql
db=pymysql.connect(“localhost”,”ayushi”,”yourpassword”,”demo”)
caching sha2: succeeded by fast path.
cursor=db.cursor()
cursor.execute(“DROP TABLE IF EXISTS student”) #This drops the table and replaces it
query=”””CREATE TABLE student(
fname VARCHAR(20), lname VARCHAR(20),
age INT, enrolment_no VARCHAR(12))”””
cursor.execute(query)
db.close()
如何在Python数据库中插入一条记录?
让我们试着在'student'中插入一条记录。
import pymysql
db=pymysql.connect(“localhost”,”ayushi”,”yourpassword”,”demo”)
caching sha2: succeeded by fast path.
cursor=db.cursor()
query=’INSERT INTO student VALUES(“Ayushi”,”Sharma”,22,”0812CS141028")’
try:
cursor.execute(query)
db.commit() #Commit writing to the database
except:
db.rollback() #Rollback the transaction if not complete
1
db.close()
让我们检查一下这是否对数据库做了任何改变。在命令提示符下
mysql> select * from student;
+ - - - - + - - - - + - - - + - - - - - - - +
| fname | lname | age | enrolment_no |
+ - - - - + - - - - + - - - + - - - - - - - +
| Ayushi | Sharma | 22 | 0812CS141028 |
+ - - - - + - - - - + - - - + - - - - - - - +
一组中的1行 (0.00 sec)
如何在Python数据库中读取记录?
现在我们如何从数据库中获取数值?让我们举个例子,从'student'中获取大于22岁的学生记录。为此我们添加了另一条记录。
import pymysql
db=pymysql.connect(“localhost”,”ayushi”,”yourpassword”,”demo”)
caching sha2: succeeded by fast path.
cursor=db.cursor()
query=”select * from student where age>22"
try:
cursor.execute(query)
resultset=cursor.fetchall() #To fetch all records that satisfy
for record in resultset:
fname=record[0]
lname=record[1]
age=record[2]
enrolment_no=record[3]
print(f”Student: {fname} {lname}; Enrolment: {enrolment_no}; Age: {age}”)
except:
print(“Sorry, we encountered a problem”)
1
Student: Megha Sharma; Enrolment: 0812CS141015; Age: 24
db.close()
我们有以下方法和属性-
fetchone()- 这个方法从查询的结果集中获取下一条记录。
fetchall()- 这是获取整个结果集;它将不包括已经提取的记录。
rowcount- 这是一个属性。它返回一个整数,表示对execute()的调用所影响的记录数。
请看Python 3中的XML处理 | XML解析器
如何在Python数据库中更新记录?
要更新现有的记录,我们可以简单地使用一个SQL查询来实现。
import pymysql
db=pymysql.connect(“localhost”,”ayushi”,”yourpassword”,”demo”)
caching sha2: succeeded by fast path.
cursor=db.cursor()
query=”update student set age=age+1 where age<=22"
try:
cursor.execute(query)
db.commit()
except:
db.rollback()
1
db.close()
让我们看看这是否对实际的数据库做了任何改变。在你的命令提示符中
mysql> select * from student;
+ - - - - + - - - - + - - - + - - - - - - - +
| fname | lname | age | enrolment_no |
+ - - - - + - - - - + - - - + - - - - - - - +
| Ayushi | Sharma | 23 | 0812CS141028 |
| Megha | Sharma | 24 | 0812CS141015 |
+ - - - - + - - - - + - - - + - - - - - - - +
一组有2行 (0.00 sec)
如何在Python数据库中删除记录?
我们也可以用Python从数据库中删除记录。
import pymysql
db=pymysql.connect(“localhost”,”ayushi”,”swaysway7!”,”demo”)
caching sha2: succeeded by fast path.
cursor=db.cursor()
query=”delete from student where age>23"
try:
cursor.execute(query)
db.commit()
except:
db.rollback()
1
db.close()
而在命令提示符下
mysql> select * from student;
+ - - - - + - - - - + - - - + - - - - - - - +
| fname | lname | age | enrolment_no |
+ - - - - + - - - - + - - - + - - - - - - - +
| Ayushi | Sharma | 23 | 0812CS141028 |
+ - - - - + - - - - + - - - + - - - - - - - +
一组中的1行 (0.00秒)
提交、回滚和断开连接
提交命令告诉数据库最终完成对数据库的写入。回滚可以让我们恢复变化,回到之前的状态。对于提交,你可以使用commit(),而对于回滚,你可以使用rollback()。
让我们讨论一下Python网络编程|Python Socket编程
在我们完成了对数据库的操作之后,我们应该关闭数据库以释放资源。为此我们使用close()。如果你不明白这些,我们建议阅读一下数据库中事务的基本属性。
交易中的错误
当持有一个事务时,你可能会遇到十种不同的错误。
Python数据库访问 - Python 3 MySQL
a. 错误
这是错误的基类,是StandardError的子类。
b. InterfaceError
这是 Error 的一个子类,Python 使用它来处理与数据库访问模块有关的错误。
c. 数据库错误(DatabaseError
这是 Error 的一个子类,Python 使用它来处理数据库错误。
d. 操作性错误
这是 DatabaseError 的一个子类。当Python失去与数据库的连接时,它会抛出这个错误。
这可能发生在我们没有选择一个数据库的时候。
让我们来探索Python Web框架--一个带有解释的详细列表
e. DataError
这是DatabaseError的一个子类。当数据中出现错误时,Python 会使用它。
f. 内部错误
这是 DatabaseError 的一个子类。Python 使用它来处理我们用于数据库访问的模块内部的错误。
g. 完整性错误(IntegrityError
也是DatabaseError的一个子类。Python 用它来处理对关系完整性有损害的情况。
当你试图在数据库中输入重复的记录时,这可能发生。
h. 编程错误
这是DatabaseError的一个子类。像糟糕的表名这样的错误会导致这种情况。
当我们试图创建一个重复的数据库时,这可能会发生。
i. 不支持的错误
是DatabaseError的一个子类。当我们试图调用它不支持的功能时,Python 会引发这个错误。
j. 警告
这是 StandardError 的一个子类。Python 用它来处理非致命的问题。
所以,这就是关于Python数据库访问的全部内容。希望你喜欢我们的解释。
https://i.imgur.com/W3G8gw8.png
总结
因此,现在你知道了如何使用Python和MySQL访问数据库。此外,我们看到了如何进行Python数据库访问,以及如何在Python 3中创建数据库,还进行了插入、读取、更新、删除、提交、回滚和断开连接等操作。最后,我们介绍了如何处理Python数据库访问和PyMySQL中的错误以及安装和Python数据库访问的好处。今天就讲到这里。请在下面的评论中提出任何疑问。
用Python为MySQL上传CSV到JSON
无可否认,我已经一头扎进了MySQL中的JSON世界。我也对Python情有独钟,我发现自己在日常工作中作为管道调查数据分析师使用了大量的Python。
CSV无处不在! 工作中的数据,网络上的数据,甚至是我的个人生活(你会看到)。对于使用这两种技术的人来说,将CSV数据加载到MySQL中并不新鲜。事实上,有几种方法可以让你的CSV数据进入MySQL。
我写了一篇文章,Pyodbc SQL CRUD - Create: 例子,你可以阅读我写的关于使用Pyodbc模块加载CSV数据的文章。但是,如何将CSV数据(通常是字符串)类型转换为兼容的JSON数据类型?然后将JSON数据推送到MySQL的JSON列中?我的朋友们,这就是这篇文章的重点。事实证明,Python的csv和json标准库使整个过程几乎没有痛苦。继续阅读,看看我设计的一个简单脚本...
使用的操作系统、软件和数据库。
OpenSuse Leap 15.1
Python 3.7.3
在Python中处理JSON数据
https://realpython.com/python-json/
如何在Python中格式化日期
https://stackabuse.com/converting-strings-to-datetime-in-python/
在Python中把字符串转换为日期时间
https://stackabuse.com/how-to-format-dates-in-python/
我有一个CSV文件,我存储了行走的统计数据。
带有数据的CSV文件...
为了存储JSON数据,我们需要一个JSON列。表'j_walking'是目标目的地,并且有一个'stats'列,就是为了这个目的。
MySQL localhost:33060+ ssl walking SQL > DESC j_walking;
+ - - - -+ - - - + - - - + - - -+ - - - - -+ - - - -+
| 字段 | 类型 | 空值 | 关键 | 默认 | 额外 |
+ - - - -+ - - - + - - - + - - -+ - - - - -+ - - - -+
| stats | json | YES | NULL | |
+ - - - -+ - - - + - - - + - - -+ - - - - -+ - - - -+
一组中的1行 (0.0034秒)
下面显示的当前数据行提供了一个格式和模式的例子。
MySQL localhost:33060+ ssl walking SQL > SELECT JSON_PRETTY(stats) FROM j_walking LIMIT 3\G
*************************** 1. row ***************************
JSON_PRETTY(stats): {
“mph”: 3.2,
“duration”: “00:33:18”,
“cal_burned”: 181.1,
“day_walked”: “2019–01–02”,
“shoes_worn”: “Keen Koven WP”,
“miles_walked”: 1.76
}
*************************** 2. row ***************************
JSON_PRETTY(stats): {
“mph”: 3.2,
“duration”: “00:38:07”,
“cal_burned”: 207.3,
“day_walked”: “2019–01–07”,
“shoes_worn”: “Oboz Sawtooth Low”,
“miles_walked”: 2.03
}
*************************** 3. row ***************************
JSON_PRETTY(stats): {
“mph”: 3.2,
“duration”: “00:40:07”,
“cal_burned”: 218.2,
“day_walked”: “2019–01–08”,
“shoes_worn”: “Oboz Sawtooth Low”,
“miles_walked”: 2.13
}
3 rows in set (0.0011 sec)
在对一个可行的函数进行原型设计的过程中,下图所示的JSON输出示例并不完全符合要求的格式。虽然它类似于我想要的最终数据结构,但所有的数字值都是字符串,而不是它们的数字等价物。
所有数据值为字符串的JSON文件...
这段工作代码提供了所需的解决方案。通过各种方式,精明的读者和开发者请在下面评论任何你认为我应该修改和改进的地方。
import csv
import json
import datetime
import os
‘’’
Simple script that converts csv file to json file
‘’’
def csv_to_json(csv_in_file, out_json_file):
try:
if os.path.isfile(csv_in_file):
# CSV 1st row header names
fieldnames = (‘day_walked’, ‘cal_burned’, ‘miles_walked’,
‘duration’, ‘mph’, ‘shoe_id’)
with open(csv_in_file, ‘r’) as f:
csv_reader = csv.DictReader(f, fieldnames)
next(csv_reader) # Advancing past the header row
with open(out_json_file, ‘w’) as json_f:
for row in csv_reader:
# Typecasting all columns to appropriate data type
row[‘day_walked’] = datetime.datetime.strptime(
row[‘day_walked’], ‘%Y-%m-%d’).date()
row[‘cal_burned’] = float(row[‘cal_burned’])
row[‘miles_walked’] = float(row[‘miles_walked’])
row[‘duration’] = datetime.datetime.strptime(
row[‘duration’], ‘%H:%M:%S’).time()
row[‘mph’] = float(row[‘mph’])
row[‘shoe_id’] = int(row[‘shoe_id’])
json.dump(row, json_f, default=str)
json_f.write(‘\n’)
else:
print(‘That CSV file does not exist.’)
except Exception as e:
raise e
if __name__ == ‘__main__’:
csv_to_json()
我将指出csv_to_json函数中的一些关键区域,这些区域对于成功的处理至关重要。
fieldnames = ('day_walked', 'cal_burned', 'miles_walked', 'duration', 'mph', 'shoe_id') - 通过设置字段名(或列名),我基本上是指定了JSON键的内容。
next(csv_reader) - 超过字段名的标题行前进,禁止将该行写入输出文件。
通过名称访问每一列--或者说是键,因为我使用的是DictReader--使我能够将所有的字段类型化为适当的数据类型(例如,row['cal_burned'] = float(row['cal_burned'])
json.dump() 方法处理Python对象的实际写入--以及它们转换后的JSON等价物--到JSON文件中。
现在到了关键时刻。让我们调用 csv_to_json() 函数,产生所需的 JSON 文件。
from csv_to_json import csv_to_json
csv_to_json(r’/home/joshua/env_37/dec_2019_hiking_stats.csv’, ‘/home/joshua/env_37/dec_2019_hiking_stats.json’)
带有类型化的数据类型的JSON文件...
Python作为一种语言的便利性是吸引我的众多因素之一。用Python操纵CSV数据是我最喜欢的功能之一。而且,由于csv和json模块被嵌入到语言中,这两个模块都是现成的,不需要第三方的软件包。
如果您对这篇文章有任何问题或建议,请随时在下面评论。
Josh Otwell对研究和成长为一名SQL开发人员和博客有很大的热情。他最喜欢的活动是把鼻子埋在一本好书、一篇文章或Linux命令行中。其中,他喜欢桌面RPG游戏,阅读幻想小说,并与他的妻子和两个女儿共度时光。
使用PyMySQL。Python的MySQL库
用于与MySQL交互的轻量级Python库。
快到周五晚上了,H+S的团队已经准备好做饭了。把灯光调暗,穿上更舒适的衣服,我们将带你进入这个100%的有机风味大餐。今晚的菜单?一个Python MySQL库。PyMySQL。
PyMySQL是一个轻量级的库,非常适合于简单的脚本。如果你想连接到一个MySQL数据库并执行一些简单的查询,那就不要再找了。PyMySQL不会给我们提供像SQLAlchemy这样的库所具有的那种花哨的功能,如果我们想建立一个快速的端点,这很好。PyMySQL的一个伟大用例是在AWS Lambda(或其他无服务器功能)中使用。我们将讨论这个问题,但现在,让我们来做一些好东西。
加热炉子
打开煤气,准备好桌子,摆上你最喜欢的盘子系列!这就是我们的工作。这是正确的;我们正在谈论模板。你知道它的到来:每次你想做一些有形的酷事时,我们都需要进入管理连接和什么的业务。为了减轻痛苦,我将与你分享一个处理PyMySQL打开连接的首选方法。
首先,我们需要创建一个配置文件。与SQLAlchemy不同,PyMySQL不支持开箱即用的数据库URI字符串。正因为如此,我们需要为数据库连接的每个部分设置变量,如用户名、密码等。
"""Config values."""
from os import environ
class Config:
# Database config
db_user = environ.get('DATABASE_USERNAME')
db_password = environ.get('DATABASE_PASSWORD')
db_host = environ.get('DATABASE_HOST')
db_port = environ.get('DATABASE_PORT')
db_name = environ.get('DATABASE_NAME')
""配置值。"""
from os import environ
class Config:
# 数据库配置
我们从一个.env文件中提取这些值:为了安全起见,我推荐这种做法。
肉和土豆
我将在一个名为Database的类中包含我们应用程序的所有数据库逻辑,以包含与数据库连接有关的所有变量和函数。
class Database:
"""Database connection class."""
def __init__(self, config):
self.host = config.db_host
self.username = config.db_user
self.password = config.db_password
self.port = config.db_port
self.dbname = config.db_name
self.conn = None
初始化这个类将我们的数据库连接变量保存到这个类的实例中,同时创建一个self.conn变量用于管理连接。我们通过将我们的config对象传递给Database来创建这个类的实例。
from config import Config
db = Database(config)
在初始化了我们的类之后,我们就可以开始做饭了。
设置表
我们将为我们的类添加的第一个方法将被称为open_connection(),以管理到我们数据库的连接的打开。在这里我们设置一个函数,将基本的连接逻辑和错误信息从我们的应用程序中分离出来。
import sys
import pymysql
import logging
class Database:
"""Database connection class."""
...
def open_connection(self):
"""Connect to MySQL Database."""
try:
if self.conn is None:
self.conn = pymysql.connect(self.host,
user=self.username,
passwd=self.password,
db=self.dbname,
connect_timeout=5)
except pymysql.MySQLError as e:
logging.error(e)
sys.exit()
finally:
logging.info('Connection opened successfully.')
输入sys
数据库连接类
连接到MySQL数据库
尝试, 如果self.conn是None。
最后 logging.info('连接成功打开。')
我们看一下我们的类的变量self.conn,作为我们的连接对象。通过在类的自我上设置conn,我们可以让这个类的所有方法针对同一个数据库连接工作,而不是为每个查询打开和关闭连接。
openConnection()会检查self.conn是否已经存在。如果连接不存在,我们的函数将尝试用给定的凭证连接到我们的MySQL数据库。我们在这里也有一些逻辑,通过利用PyMySQL内置的
pymysql.MySQLError异常类型,在出错时抛出一个错误。在与数据库打交道时,习惯于看到大量的try/except/finally语句。
现在我们可以在我们类的所有方法之间共享openConnection(),并且只在需要时打开连接。
入口
抛开这些无聊的东西,让我们来探讨一些美好的东西。我们将从一个基本的用例开始:从一个表中选择所有的行。
class Database:
"""Database connection class."""
def run_query(self, query):
"""Execute SQL query."""
try:
self.open_connection()
with self.conn.cursor() as cur:
records = []
cur.execute(query)
result = cur.fetchall()
for row in result:
records.append(row)
cur.close()
return records
except pymysql.MySQLError as e:
print(e)
finally:
if self.conn:
self.conn.close()
self.conn = None
print('Database connection closed.')
run_query()试图使用我们先前创建的open_connection()函数来打开一个连接。打开连接后,我们就可以自由地运行我们想要的任何查询。
我们的函数被传递给一个叫做query的参数,它代表我们想要运行的任何SQL查询(又称:SELECT * FROM [table])。为了执行这样一个查询,我们需要打开一个游标,我们用这一行来做。
with self.conn.cursor() as cur: ...
当cur打开时,我们能够运行所有我们想要的查询。让我们把它提高一个档次。
选择数据的行数
现在打开cur,我们可以针对cur调用一些方法。
cur.execute([QUERY])
对cur调用execute()将在我们的游标对象中运行一个查询。
cur.fetchall()
在运行一个产生记录的查询后,我们可以通过对cur调用fetchall()来查看所有由我们的查询返回的记录。正如你所看到的,我们应该在每个游标上只执行一个查询。否则,我们就会重复写上一次查询的结果。试图打印.fetchall()的结果,会得到一个整数,代表获取的行数。
cur.fetchone()
与fetchall()不同,fetchone()只获取我们查询返回的第一行。如果我们知道只有一条记录被返回,应该
使用.fetchone()
cur.close()
当我们最终完成了查询,我们应该用close()关闭游标。
run_query()
假设我们传递的查询是一个SELECT查询,这就是为什么我们要把结果保存到一个数组中。如果我们运行的是UPDATE或DELETE查询,这就没有什么意义了,因为什么都不会被返回。
更新数据的行数
如果我们不是在选择数据,而是在修改它呢?看看我们的函数如何变化。
def run_query(self, query):
"""Execute SQL query."""
try:
self.open_connection()
with self.conn.cursor() as cur:
result = cur.execute(query)
self.conn.commit()
affected = f"{cur.rowcount} rows affected."
cur.close()
return affected
conn.commit()
运行commit()实际上是提交了我们查询中的变化。如果你忘记了这一点,你的数据变化实际上不会被保存(这也适用于DELETE和INSERT语句)
cur.rowcount 返回受改变数据的查询影响的行数。
结合上述内容
所以现在我们有一个期望SELECT语句的run_query()版本,和一个期望突变的版本。我们怎样才能使这个函数足够聪明地处理两种情况,并返回最合理的结果呢?在执行之前,检查一下SELECT这个词是否存在于查询中,怎么样?
def run_query(self, query):
"""Execute SQL query."""
try:
self.open_connection()
with self.conn.cursor() as cur:
if 'SELECT' in query:
records = []
cur.execute(query)
result = cur.fetchall()
for row in result:
records.append(row)
cur.close()
return records
else:
result = cur.execute(query)
self.conn.commit()
affected = f"{cur.rowcount} rows affected."
cur.close()
return affected
except pymysql.MySQLError as e:
print(e)
finally:
if self.conn:
self.conn.close()
self.conn = None
logging.info('Database connection closed.')
现在,我们有了一个可以处理这两种情况的函数! 当然,这个实现并不是万无一失的:如果你的某一列恰好命名为SELECT(或其他),你可能会遇到一些问题。我想,不要那样做。
甜品
希望你能发现我们的小晚餐约会是有用的。如果你正在寻找一些复制和粘贴的源码来开始使用我们自己的PyMySQL,请随时在Github上查看这个源代码。如果这太多了,请随意复制+粘贴下面的内容。
import sys
import pymysql
import logging
class Database:
"""Database connection class."""
def __init__(self, config):
self.host = config.db_host
self.username = config.db_user
self.password = config.db_password
self.port = config.db_port
self.dbname = config.db_name
self.conn = None
def open_connection(self):
"""Connect to MySQL Database."""
try:
if self.conn is None:
self.conn = pymysql.connect(self.host,
user=self.username,
passwd=self.password,
db=self.dbname,
connect_timeout=5)
except pymysql.MySQLError as e:
logging.error(e)
sys.exit()
finally:
logging.info('Connection opened successfully.')
def run_query(self, query):
"""Execute SQL query."""
try:
self.open_connection()
with self.conn.cursor() as cur:
if 'SELECT' in query:
records = []
cur.execute(query)
result = cur.fetchall()
for row in result:
records.append(row)
cur.close()
return records
else:
result = cur.execute(query)
self.conn.commit()
affected = f"{cur.rowcount} rows affected."
cur.close()
return affected
except pymysql.MySQLError as e:
print(e)
finally:
if self.conn:
self.conn.close()
self.conn = None
logging.info('Database connection closed.')
我们感谢你们所有人加入我们这次诱人的冒险
祝你胃口好。