27 使用 Python 操作 MySQL 資料庫
1. Python 資料庫訪問介面
1.1 簡介
Python 所有的資料庫介面程式都在一定程度上遵守 Python DB-API 規範。Python DB-API 是一個規範,它定義了一系列必須的物件和資料庫存取方式,以便為各種各樣的底層資料庫系統和多種多樣的資料庫介面程式提供一致的訪問介面。
在沒有 Python DB-API 之前,各資料庫之間的應用介面非常混亂,實現各不相同。如果專案需要更換資料庫時,則需要做大量的修改,非常不便。Python DB-API 的出現就是為了解決這樣的問題。
由於 Python DB-API 為不同的資料庫提供了一致的訪問介面, 在不同的資料庫之間移植程式碼成為一件輕鬆的事情。
1.2 connect() 方法
connect 方法生成一個 connect 物件, 通過這個物件來訪問資料庫。connect 的引數如下:
引數 | 功能 |
---|---|
user | 訪問資料庫的使用者 |
password | 訪問資料庫的密碼 |
host | Mysql 資料庫服務所在的主機 |
port | Mysql 資料庫服務的埠號,預設值為 3306 |
db | 資料庫名 |
charset | 字元編碼 |
使用者以命名引數的方式開啟資料庫,例如:
pymysql.connect(
host = '192.168.168.168',
port = 3306,
user = 'root' ,
password = 'mysql',
db = 'school',
charset = 'utf8'
)
1.3 connect 物件
使用 connect() 方法與資料庫連線成功後,connect() 方法返回一個 connect() 物件。
與資料庫進行通訊時, 向 connect 物件傳送 SQL 查詢命令, 並 connect 物件接收 SQL 查詢結果。
connect 物件提供瞭如下常用方法:
方法 | 功能 |
---|---|
close() | 關閉資料庫連線 |
commit() | 提交當前事務 |
rollback() | 取消當前事務 |
cursor() | 建立一個遊標物件用於執行 SQL 查詢命令 |
1.4 cursor 物件
cursor 物件用於執行 SQL 命令和得到 SQL 查詢結果。cursor 物件提供如下方法:
方法 | 功能 |
---|---|
close() | 關閉遊標物件 |
execute() | 執行一個數據庫查詢或命令 |
fetchone() | 返回結果集的下一行 |
fetchall() | 返回結果集中所有行 |
2. 安裝 pymysql
pymysql 是 python 訪問 mysql 資料庫的模組。首先檢查是否已經安裝了 pymsql 模組,在 python 互動模式下 import pymysql,如下所示:
>>> import pymysql
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'pymysql'
如果出現錯誤:ModuleNotFoundError,則表示還沒有安裝 pymysql,使用 pip3 install mysql 安裝 pymysql,如下所示:
C:\Users\Administrator>pip3 install pymysql
Collecting pymysql
...
Installing collected packages: pymysql
Successfully installed pymysql-0.9.3
3. 建立資料庫
3.1 編寫資料庫指令碼 db.sql
SET character_set_database=utf8;
SET character_set_server=utf8;
- 設定資料庫編碼為 utf8
DROP DATABASE IF EXISTS school;
CREATE DATABASE school;
USE school;
- 如果已經存在名稱為 school 的資料庫,則刪除
- 建立名稱為 school 的資料庫
- 使用名稱為 school 的資料庫
CREATE TABLE students(
sno VARCHAR(32),
name VARCHAR(32),
age INT
);
- 在資料庫 school 中建立表 students,表 students 包含 3 個欄位:
- sno,學號
- name,姓名
- age,年齡
INSERT INTO students(sno, name, age) VALUES ('1', '張三', '20');
INSERT INTO students(sno, name, age) VALUES ('2', '李四', '21');
- 向表 students 中插入兩條資料,用於測試
3.2 執行資料庫指令碼 db.sql
啟動 mysql 命令列,輸入 source db.sql,執行 db.sql 中的 SQL 命令,如下所示:
$ sudo mysql
mysql> source db.sql
Query OK, 0 rows affected, 1 warning (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 1 row affected (0.02 sec)
Query OK, 1 row affected (0.00 sec)
Database changed
Query OK, 0 rows affected (0.02 sec)
Query OK, 1 row affected (0.00 sec)
Query OK, 1 row affected (0.01 sec)
4. 連線資料庫
def open_conn():
global conn
global cursor
conn = pymysql.connect(
host = 'localhost',
user = 'root',
password = '',
db = 'school',
charset='utf8'
)
cursor = conn.cursor()
- 在第 1 行,定義函式 open_conn 開啟 mysql 資料庫
- 在第 2 行,宣告全域性變數 conn
- 在第 3 行,宣告全域性變數 cursor
- 在第 5 行,呼叫 connect 方法建立 connect 物件
- 在第 12 行,呼叫 cursor 方法建立 cursor 物件
def close_conn():
cursor.close()
conn.commit()
conn.close()
- 在第 1 行,定義函式 close_conn 關閉 mysql 資料庫
- 在第 3 行,關閉資料庫之前呼叫 commit() 方法,提交對資料庫的修改
5. 查詢資料
5.1 使用 fetchone 查詢資料
def query_students_fetchone():
sql = 'SELECT * FROM students'
rows = cursor.execute(sql)
print('There are %d students' % rows)
for i in range(rows):
student = cursor.fetchone()
print(student)
- 在第 1 行,定義函式 query_students_fetchone,使用 fetchone 方法查詢資料
- 在第 3 行,cursor.execute(sql) 返回查詢記錄的條數
- 在第 7 行,使用 fetchone() 獲取一條查詢記錄
編寫測試程式如下:
open_conn()
query_students_fetchone()
close_conn()
程式輸出如下:
There are 2 students
('1', '張三', 20)
('2', '李四', 21)
- 查詢記錄是一個元組
- 第 0 項是 sno
- 第 1 項是 name
- 第 2 項是 age
5.2 使用 fetchall 查詢資料
def query_students_fetchall():
sql = 'SELECT * FROM students'
rows = cursor.execute(sql)
print('There are %d students' % rows)
students = cursor.fetchall()
for student in students:
print(student)
- 在第 1 行,定義函式 query_students_fetchall,使用 fetchall 方法查詢資料
- 在第 3 行,cursor.execute(sql) 返回查詢記錄的條數
- 在第 6 行,使用 fetchall() 獲取所有的查詢記錄
編寫測試程式如下:
open_conn()
query_students_fetchall()
close_conn()
程式輸出如下:
There are 2 students
('1', '張三', 20)
('2', '李四', 21)
6. 增加資料
def add_student(sno, name, age):
sql = 'INSERT INTO students(sno, name, age) VALUES("%s", "%s", %d)' % (sno, name, age)
rows = cursor.execute(sql)
print('Insert %d students' % rows)
- 在第 1 行,定義函式 add_student(sno, name, age),向表 students 中插入一條資料
- 在第 3 行,cursor.execute(sql) 返回插入記錄的條數
編寫測試程式如下:
open_conn()
add_student('3', '王五', 18)
add_student('4', '劉六', 19)
query_students_fetchone()
close_conn()
程式輸出如下:
Insert 1 students
Insert 1 students
There are 4 students
('1', '張三', 20)
('2', '李四', 21)
('3', '王五', 18)
('4', '劉六', 19)
7. 修改資料
def update_student(sno, name, age):
sql = 'UPDATE students SET name="%s", age=%d WHERE sno="%s"' % (name, age, sno)
rows = cursor.execute(sql)
print('UPDATE %d students' % rows)
- 在第 1 行,定義函式 update_student(sno, name, age),根據學生的 sno 修改 name 和 age
- 在第 3 行,cursor.execute(sql) 返回修改記錄的條數
編寫測試程式如下:
open_conn()
update_student('3', 'WangWu', 28)
update_student('4', 'LiuLiu', 29)
query_students_fetchone()
close_conn()
程式輸出如下:
UPDATE 0 students
UPDATE 0 students
There are 4 students
('1', '張三', 20)
('2', '李四', 21)
('3', 'WangWu', 28)
('4', 'LiuLiu', 29)
8. 刪除資料
def delete_student(sno):
sql = 'DELETE FROM students WHERE sno="%s"' % (sno)
rows = cursor.execute(sql)
print('DELETE %d students' % rows)
- 在第 1 行,定義函式 delete_student(sno),刪除表 students 中學號為 sno 的資料
- 在第 3 行,cursor.execute(sql) 返回刪除記錄的條數
編寫測試程式如下:
open_conn()
delete_student('3')
delete_student('4')
query_students_fetchone()
close_conn()
程式輸出如下:
DELETE 1 students
DELETE 1 students
There are 2 students
('1', '張三', 20)
('2', '李四', 21)