PyMySQL 是在 Python3.x 版本中用於連接 MySQL 服務器的一個庫,Python2中則使用mysqldb。
安裝:
pip3 install PyMySQL
常用參數:
pymysql.Connect() 參數說明
host(str) mysql服務器地址
port(int) 端口
user(str) 用戶名
passwd(str) 密碼
db(str) 數據庫名稱
charset(str) 鏈接編碼
connection() 對象支持的方法
cursor() 使用該鏈接創建並返回游標
commit() 提交當前事務
rollback() 回滾當前事務
close() 關閉鏈接
curser()對象支持的方法
execute(op) 執行一個數據庫的查詢命令
fetchone() 取得結果集的下一行
fetchmany(size) 獲取結果集的下幾行
fetchall() 獲取結果集中的所有行
rowcount() 返回數據條數或影響行數
close() 關閉游標對象
lastrowid 獲取自增ID
連接數據庫;
import pymysql
connect = pymysql.Connect( host = 'localhost', port = 3306, user = 'root', passwd = '123456', db = 'python', charset = 'utf8', cursorclass = pymysql.cursors.DictCursor // 指定類型 ) //獲取游標 cursor = connect.cursor()
插入數據:
sql = "INSERT INTO trade (name, account, saving) VALUES ( '%s', '%s', %.2f )" data = ('雷軍', '13512345678', 10000) cursor.execute(sql % data) connect.commit() print('成功插入', cursor.rowcount, '條數據')
// 獲取插入的ID(一定要在commit之前獲取)
last_id = curs.lastrowid
修改數據:
sql = "UPDATE trade SET saving = %.2f WHERE account = '%s' " data = (8888, '13512345678') cursor.execute(sql % data) connect.commit() print('成功修改', cursor.rowcount, '條數據')
查詢數據:
sql = "SELECT name,saving FROM trade WHERE account = '%s' " data = ('13512345678',) cursor.execute(sql % data) for row in cursor.fetchall(): print("Name:%s\tSaving:%.2f" % row) print('共查找出', cursor.rowcount, '條數據')
# 返回結果是一個字典類型數據
刪除數據:
sql = "DELETE FROM trade WHERE account = '%s' LIMIT %d" data = ('13512345678', 1) cursor.execute(sql % data) connect.commit() print('成功刪除', cursor.rowcount, '條數據')
事務處理:
sql_1 = "UPDATE trade SET saving = saving + 1000 WHERE account = '18012345678' " sql_2 = "UPDATE trade SET expend = expend + 1000 WHERE account = '18012345678' " sql_3 = "UPDATE trade SET income = income + 2000 WHERE account = '18012345678' " try: cursor.execute(sql_1) # 儲蓄增加1000 cursor.execute(sql_2) # 支出增加1000 cursor.execute(sql_3) # 收入增加2000 except Exception as e: connect.rollback() # 事務回滾 print('事務處理失敗', e) else: connect.commit() # 事務提交 print('事務處理成功', cursor.rowcount) # 關閉連接 cursor.close() connect.close()
游標控制
所有的數據查詢操作均基於游標,我們可以通過cursor.scroll(num, mode)
控制游標的位置。
cursor.scroll(1, mode='relative') # 相對當前位置移動 cursor.scroll(2, mode='absolute') # 相對絕對位置移動
設置游標類型
查詢時,默認返回的數據類型為元組,可以自定義設置返回類型。支持5種游標類型:
- Cursor: 默認,元組類型
- DictCursor: 字典類型
- DictCursorMixin: 支持自定義的游標類型,需先自定義才可使用
- SSCursor: 無緩沖元組類型
- SSDictCursor: 無緩沖字典類型
無緩沖游標類型,適用於數據量很大,一次性返回太慢,或者服務端帶寬較小時。
事務處理
-
開啟事務
connection.begin()
-
提交修改
connection.commit()
-
回滾事務
connection.rollback()
防 SQL 注入
轉義特殊字符 connection.escape_string(str)
參數化語句 支持傳入參數進行自動轉義、格式化 SQL 語句,以避免 SQL 注入等安全問題。
# 插入數據(元組或列表) effect_row = cursor.execute('INSERT INTO `users` (`name`, `age`) VALUES (%s, %s)', ('mary', 18)) # 插入數據(字典) info = {'name': 'fake', 'age': 15} effect_row = cursor.execute('INSERT INTO `users` (`name`, `age`) VALUES (%(name)s, %(age)s)', info) # 批量插入 effect_row = cursor.executemany( 'INSERT INTO `users` (`name`, `age`) VALUES (%s, %s) ON DUPLICATE KEY UPDATE age=VALUES(age)', [ ('hello', 13), ('fake', 28), ])
示例:
1. 執行SQL
cursor = connection.cursor() # 創建數據表 effect_row = cursor.execute(''' CREATE TABLE `users` ( `name` varchar(32) NOT NULL, `age` int(10) unsigned NOT NULL DEFAULT '0', PRIMARY KEY (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ''') # 插入數據(元組或列表) effect_row = cursor.execute('INSERT INTO `users` (`name`, `age`) VALUES (%s, %s)', ('mary', 18)) # 插入數據(字典) info = {'name': 'fake', 'age': 15} effect_row = cursor.execute('INSERT INTO `users` (`name`, `age`) VALUES (%(name)s, %(age)s)', info) connection.commit()
# 獲取游標 cursor = connection.cursor() # 批量插入 effect_row = cursor.executemany( 'INSERT INTO `users` (`name`, `age`) VALUES (%s, %s) ON DUPLICATE KEY UPDATE age=VALUES(age)', [ ('hello', 13), ('fake', 28), ]) connection.commit()
注意: INSERT,UPDATE,DELETE等修改操作,需要手動執行commit()完成對數據的修改提交
2.查詢數據
# 執行查詢 SQL cursor.execute('SELECT * FROM `users`') # 獲取單條數據 cursor.fetchone() # 獲取前N條數據 cursor.fetchmany(3) # 獲取所有數據 cursor.fetchall()
常見問題:
1.
pymysql.err.ProgrammingError: (1064, 'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \'fas好",\'wozhidaole知道了\'" where title = "好"\' at line 1')
字符串中出現引號,導致SQL語句發生錯誤,需要進行轉義
pymysql.escape_string(str)