# PyMySQL 教程

> 原文： [http://zetcode.com/python/pymysql/](http://zetcode.com/python/pymysql/)

PyMySQL 教程展示了如何使用 PyMySQL 模块在 Python 中对 MySQL 进行编程。

## PyMySQL

PyMySQL 是基于 PEP 249 的纯 Python MySQL 客户端库。大多数公共 API 与`mysqlclient`和`MySQLdb`兼容。 PyMySQL 可与 MySQL 5.5+和 MariaDB 5.5+ 一起使用。

MySQL 是领先的开源数据库管理系统。 它是一个多用户，多线程的数据库管理系统。 MySQL 在网络上特别流行。

## PyMySQL 安装

```py
$ sudo pip3 install PyMySQL

```

我们使用`pip3`工具安装 PyMySQL。

## PyMySQL 版本示例

在下面的示例中，我们获取 MySQL 的版本。

`version.py`

```py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import pymysql

con = pymysql.connect('localhost', 'user17', 
    's$cret', 'mydb')

with con:

    cur = con.cursor()
    cur.execute("SELECT VERSION()")

    version = cur.fetchone()

    print("Database version: {}".format(version[0]))

```

在 MySQL 中，我们可以使用`SELECT VERSION()`获取 MySQL 的版本。

```py
import pymysql

```

我们导入`pymysql`模块。

```py
con = pymysql.connect('localhost', 'user17', 
    's$cret', 'mydb')

```

我们使用`connect()`连接到数据库。 我们传递四个参数：主机名，MySQL 用户名，密码和数据库名。

```py
with con:

```

使用`with`关键字，Python 解释器会自动释放资源。 它还提供错误处理。

```py
cur = con.cursor()

```

从连接对象，我们创建一个游标。 游标用于遍历结果集中的记录。

```py
cur.execute("SELECT VERSION()")

```

我们调用游标的`execute()`方法并执行 SQL 语句。

```py
version = cur.fetchone()

```

`fetchone()`方法获取查询结果集的下一行，返回单个序列，或者在没有更多数据可用时返回`None`。

```py
print("Database version: {}".format(version[0]))

```

我们打印数据库的版本。

```py
$ ./version.py 
Database version: 5.7.23-0ubuntu0.16.04.1

```

这是输出。

## PyMySQL `fetchAll`

`fetchAll()`方法检索查询结果的所有（剩余）行，并将它们作为序列序列返回。

`retrieve_all.py`

```py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import pymysql

con = pymysql.connect('localhost', 'user17', 
    's$cret', 'testdb')

with con: 

    cur = con.cursor()
    cur.execute("SELECT * FROM cities")

    rows = cur.fetchall()

    for row in rows:
        print("{0} {1} {2}".format(row[0], row[1], row[2]))

```

在示例中，我们从数据库表中检索所有城市。

```py
cur.execute("SELECT * FROM cities")

```

该 SQL 语句从`citys`表中选择所有数据。

```py
rows = cur.fetchall()

```

`fetchall()`方法获取所有记录。 它返回一个结果集。 从技术上讲，它是一个元组的元组。 每个内部元组代表表中的一行。

```py

for row in rows:
    print("{0} {1} {2}".format(row[0], row[1], row[2]))

```

我们将数据逐行打印到控制台。

```py
$ ./retrieve_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 字典的形式发送。 这样，我们可以通过列名称来引用数据。

`dictionary_cursor.py`

```py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import pymysql
import pymysql.cursors

con = pymysql.connect(host='localhost',
        user='user17',
        password='s$cret',
        db='mydb',
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor)

with con:

    cur = con.cursor()
    cur.execute("SELECT * FROM cities")

    rows = cur.fetchall()

    for row in rows:
        print(row["id"], row["name"])

```

在此示例中，我们使用字典游标获取`citys`表的第一行。

```py
con = pymysql.connect(host='localhost',
        user='user17',
        password='s$cret',
        db='mydb',
        charset='utf8mb4',
        cursorclass=pymysql.cursors.DictCursor)

```

在`connect()`方法中，我们将`pymysql.cursors.DictCursor`值传递给`cursorclass`参数。

```py
for row in rows:
    print(row["id"], row["name"])

```

我们通过`cities`表的列名称引用数据。

## PyMySQL 列标题

接下来，我们将展示如何使用数据库表中的数据打印列标题。

`column_headers.py`

```py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import pymysql

con = pymysql.connect('localhost', 'user17', 
    's$cret', 'testdb')

with con:

    cur = con.cursor()
    cur.execute("SELECT * FROM cities")

    rows = cur.fetchall()

    desc = cur.description

    print("{0:>3} {1:>10}".format(desc[0][0], desc[1][0]))

    for row in rows:    
        print("{0:3} {1:>10}".format(row[0], row[2]))

```

列名称被认为是元数据。 它们是从游标对象获得的。

```py
desc = cur.description

```

游标的`description`属性返回有关查询的每个结果列的信息。

```py
print("{0:>3} {1:>10}".format(desc[0][0], desc[1][0]))

```

在这里，我们打印并格式化表格的列名。

```py

for row in rows:    
    print("{0:3} {1:>10}".format(row[0], row[2]))

```

我们遍历并打印数据。

```py
$ ./column_headers.py 
 id       name
  1     432000
  2    1759000
  3    1280000
  4    1748000
  5    3971000
  6    8550000
  7     464000
  8    3671000

```

这是输出。

## PyMySQL 预备语句

在编写预备语句时，我们使用占位符，而不是直接将值写入语句中。 预准备的语句可提高安全性和性能。

`prepared_statement.py`

```py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import pymysql

con = pymysql.connect('localhost', 'user17', 
    's$cret', 'testdb')

# user input
myid = 4

with con:    

    cur = con.cursor()

    cur.execute("SELECT * FROM cities WHERE id=%s", myid) 

    cid, name, population  = cur.fetchone()
    print(cid, name, population)

```

在示例中，我们获得具有指定 ID 的行。

```py
cur.execute("SELECT * FROM cities WHERE id=%s", myid) 

```

我们使用由`%s`标记标识的占位符。 在执行 SQL 语句之前，将值绑定到它们的占位符。

```py
$ ./prepared_statement.py 
4 Warsaw 1748000

```

这是输出。

## PyMySQL 受影响的行

`rowcount`是只读的游标属性，它指定最后一条`SELECT`，`UPDATE`或`INSERT`语句产生的行数。

`affected_rows.py`

```py
#!/usr/bin/python3
# -*- coding: utf-8 -*-

import pymysql

con = pymysql.connect('localhost', 'user17',
   's$cret', 'mydb')

with con:

    cur = con.cursor()
    cur.execute("SELECT * FROM cities WHERE id IN (1, 2, 3)")

    # rows = cur.fetchall()

    # for row in rows:
    #     print("{0} {1} {2}".format(row[0], row[1], row[2]))

    print("The query affected {} rows".format(cur.rowcount))

```

在示例中，我们有一条`SELECT`语句选择三行。

```py
print("The query affected {} rows".format(cur.rowcount))

```

我们生成一条消息，显示受影响的行数。

```py
$ ./affected_rows.py 
The query affected 3 rows

```

这是输出。

在本教程中，我们一直在使用 PyMySQL 模块在 Python 中编写 MySQL 数据库。

您可能也对以下相关教程感兴趣： [Python SQLite 教程](/python/sqlite/)， [Python PostgreSQL 教程](/python/psycopg2/)， [PyMongo 教程](/python/pymongo/)， [Peewee 教程](/python/peewee/)， [pyDAL 教程](/python/pydal/)和 [Python 教程](/lang/python/)，或列出 [Python 教程](/all/#python)。