PyMySQL教程展示了如何使用PyMySQL模块在Python中对MySQL进行编程。
PyMySQL
PyMySQL是一个基于PEP249的纯PythonMySQL客户端库。大多数公共API都与mysqlclient和MySQLdb兼容。PyMySQL适用于MySQL5.5+和MariaDB5.5+。
MySQL是领先的开源数据库管理系统。它是一个多用户、多线程的数据库管理系统。MySQL在网络上尤其流行。
USE testdb;
DROP TABLE IF EXISTS cities;
CREATE TABLE cities(id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255), population INT);
INSERT INTO cities(name, population) VALUES('Bratislava', 432000);
INSERT INTO cities(name, population) VALUES('Budapest', 1759000);
INSERT INTO cities(name, population) VALUES('Prague', 1280000);
INSERT INTO cities(name, population) VALUES('Warsaw', 1748000);
INSERT INTO cities(name, population) VALUES('Los Angeles', 3971000);
INSERT INTO cities(name, population) VALUES('New York', 8550000);
INSERT INTO cities(name, population) VALUES('Edinburgh', 464000);
INSERT INTO cities(name, population) VALUES('Berlin', 3671000);
在本教程中,我们使用cities表。
PyMySQL安装
$ sudo pip3 install pymysql
我们使用pip3工具安装PyMySQL。
PyMySQL版本示例
在下面的例子中,我们获取MySQL的版本。
#!/usr/bin/python
import pymysql
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
try:
with con.cursor() as cur:
cur.execute('SELECT VERSION()')
version = cur.fetchone()
print(f'Database version: {version[0]}')
finally:
con.close()
在MySQL中,我们可以使用SELECTVERSION来获取MySQL的版本。
import pymysql
我们导入pymysql模块。
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
我们使用connect连接到数据库。我们传递了四个参数:主机名、MySQL用户名、密码和数据库名。
with con.cursor() as cur:
使用with关键字,Python解释器自动释放资源。它还提供错误处理。我们得到一个游标对象,它用于从结果集中遍历记录。
cur.execute('SELECT VERSION()')
我们调用游标的execute函数,执行SQL语句。
version = cur.fetchone()
fetchone函数获取查询结果集的下一行,返回单个序列,或者在没有更多数据可用时返回None。
print(f'Database version: {version[0]}')
我们打印数据库的版本。
finally:
con.close()
pymysql模块没有实现连接资源的自动处理;我们需要在finally子句中使用close显式关闭连接。
$ ./version.py Database version: 10.3.23-MariaDB-1
PyMySQLfetchAll
fetchAll方法检索查询结果的所有(剩余)行,将它们作为序列序列返回。
#!/usr/bin/python
import pymysql
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
try:
with con.cursor() as cur:
cur.execute('SELECT * FROM cities')
rows = cur.fetchall()
for row in rows:
print(f'{row[0]} {row[1]} {row[2]}')
finally:
con.close()
在示例中,我们从数据库表中检索所有城市。
cur.execute('SELECT * FROM cities')
此SQL语句从cities表中选择所有数据。
rows = cur.fetchall()
fetchall函数获取所有记录。它返回一个结果集。从技术上讲,它是一个元组的元组。每个内部元组代表表中的一行。
for row in rows:
print(f'{row[0]} {row[1]} {row[2]}')
我们将数据逐行打印到控制台。
$ ./fetch_all.py 1 Bratislava 432000 2 Budapest 1759000 3 Prague 1280000 4 Warsaw 1748000 5 Los Angeles 3971000 6 New York 8550000 7 Edinburgh 464000 8 Berlin 3671000
PyMySQL字典游标
默认游标以元组的元组形式返回数据。当我们使用字典游标时,数据以Python字典的形式发送。这样我们就可以通过列名来引用数据。
#!/usr/bin/python
import pymysql
import pymysql.cursors
con = pymysql.connect(host='localhost',
user='user7',
password='s$cret',
db='testdb',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
try:
with con.cursor() as cur:
cur.execute('SELECT * FROM cities')
rows = cur.fetchall()
for row in rows:
print(row['id'], row['name'])
finally:
con.close()
在此示例中,我们使用字典游标获取城市表的第一行。
con = pymysql.connect(host='localhost',
user='user7',
password='s$cret',
db='testdb',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
在connect函数中,我们将pymysql.cursors.DictCursor值传递给cursorclass参数。
for row in rows:
print(row['id'], row['name'])
我们通过cities表的列名引用数据。
PyMySQL列标题
接下来我们将展示如何使用数据库表中的数据打印列标题。
#!/usr/bin/python
import pymysql
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
try:
with con.cursor() as cur:
cur.execute('SELECT * FROM cities')
rows = cur.fetchall()
desc = cur.description
print(f'{desc[0][0]:<8} {desc[1][0]:<15} {desc[2][0]:>10}')
for row in rows:
print(f'{row[0]:<8} {row[1]:<15} {row[2]:>10}')
finally:
con.close()
列名被认为是元数据。它们是从游标对象中获取的。
desc = cur.description
游标的description属性返回有关查询的每个结果列的信息。
print(f'{desc[0][0]:<8} {desc[1][0]:<15} {desc[2][0]:>10}')
这里我们打印和格式化表格列名。
for row in rows:
print(f'{row[0]:<8} {row[1]:<15} {row[2]:>10}')
我们遍历并打印数据。
$ ./column_headers.py id name population 1 Bratislava 432000 2 Budapest 1759000 3 Prague 1280000 4 Warsaw 1748000 5 Los Angeles 3971000 6 New York 8550000 7 Edinburgh 464000 8 Berlin 3671000
PyMySQL转义参数
出于安全原因,传递给execute方法的参数被转义;这是为了防止SQL注入攻击。
#!/usr/bin/python
import pymysql
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
# user input
myid = 4
try:
with con.cursor() as cur:
cur.execute('SELECT * FROM cities WHERE id=%s', myid)
cid, name, population = cur.fetchone()
print(cid, name, population)
finally:
con.close()
在示例中,我们获取具有指定Id的行。
cur.execute('SELECT * FROM cities WHERE id=%s', myid)
我们使用由%s标记标识的占位符。在执行SQL语句之前,值会绑定到它们的占位符。
$ ./escaped.py 4 Warsaw 1748000
PyMySQL影响的行
rowcount是一个只读游标属性,它指定最后一个SELECT、UPDATE或INSERT语句生成的行数。
#!/usr/bin/python
import pymysql
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
try:
with con.cursor() as cur:
cur.execute('SELECT * FROM cities WHERE id IN (1, 2, 3)')
print(f'The query affected {cur.rowcount} rows')
finally:
con.close()
在示例中,我们有一个选择三行的SELECT语句。
print(f'The query affected {cur.rowcount} rows')
我们构建一条消息,显示受影响的行数。
$ ./affected_rows.py The query affected 3 rows
PyMySQL插入行
使用INSERTINTOSQL语句插入新行。
#!/usr/bin/python
import pymysql
con = pymysql.connect('localhost', 'user7',
's$cret', 'testdb')
city = (9, 'Kiev', 2887000)
try:
with con.cursor() as cur:
cur.execute('INSERT INTO cities VALUES(%s, %s, %s)',
(city[0], city[1], city[2]))
con.commit()
print('new city inserted')
finally:
con.close()
在示例中,我们向表中插入一个新城市。
cur.execute('INSERT INTO cities VALUES(%s, %s, %s)',
(city[0], city[1], city[2]))
con.commit()
在pymysql中,默认情况下自动提交是关闭的。我们需要调用commit来执行更改。
在本教程中,我们一直在使用PyMySQL模块在Python中对MySQL数据库进行编程。
访问Python教程或列出所有Python教程。
