Python 3 進階 —— 使用 PyMySQL 操做 MySQL

PyMySQL 是一個純 Python 實現的 MySQL 客戶端操做庫,支持事務、存儲過程、批量執行等。html

PyMySQL 遵循 Python 數據庫 API v2.0 規範,幷包含了 pure-Python MySQL 客戶端庫。python

安裝

pip install PyMySQL

建立數據庫鏈接

import pymysql

connection = pymysql.connect(host='localhost',
                             port=3306,
                             user='root',
                             password='root',
                             db='demo',
                             charset='utf8')

參數列表:mysql

參數 描述
host 數據庫服務器地址,默認 localhost
user 用戶名,默認爲當前程序運行用戶
password 登陸密碼,默認爲空字符串
database 默認操做的數據庫
port 數據庫端口,默認爲 3306
bind_address 當客戶端有多個網絡接口時,指定鏈接到主機的接口。參數能夠是主機名或IP地址。
unix_socket unix 套接字地址,區別於 host 鏈接
read_timeout 讀取數據超時時間,單位秒,默認無限制
write_timeout 寫入數據超時時間,單位秒,默認無限制
charset 數據庫編碼
sql_mode 指定默認的 SQL_MODE
read_default_file Specifies my.cnf file to read these parameters from under the [client] section.
conv Conversion dictionary to use instead of the default one. This is used to provide custom marshalling and unmarshaling of types.
use_unicode Whether or not to default to unicode strings. This option defaults to true for Py3k.
client_flag Custom flags to send to MySQL. Find potential values in constants.CLIENT.
cursorclass 設置默認的遊標類型
init_command 當鏈接創建完成以後執行的初始化 SQL 語句
connect_timeout 鏈接超時時間,默認 10,最小 1,最大 31536000
ssl A dict of arguments similar to mysql_ssl_set()'s parameters. For now the capath and cipher arguments are not supported.
read_default_group Group to read from in the configuration file.
compress Not supported
named_pipe Not supported
autocommit 是否自動提交,默認不自動提交,參數值爲 None 表示以服務器爲準
local_infile Boolean to enable the use of LOAD DATA LOCAL command. (default: False)
max_allowed_packet 發送給服務器的最大數據量,默認爲 16MB
defer_connect 是否惰性鏈接,默認爲當即鏈接
auth_plugin_map A dict of plugin names to a class that processes that plugin. The class will take the Connection object as the argument to the constructor. The class needs an authenticate method taking an authentication packet as an argument. For the dialog plugin, a prompt(echo, prompt) method can be used (if no authenticate method) for returning a string from the user. (experimental)
server_public_key SHA256 authenticaiton plugin public key value. (default: None)
db 參數 database 的別名
passwd 參數 password 的別名
binary_prefix Add _binary prefix on bytes and bytearray. (default: False)

執行 SQL

  • cursor.execute(sql, args) 執行單條 SQLgit

    # 獲取遊標
    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()
  • executemany(sql, args) 批量執行 SQLgithub

    # 獲取遊標
    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 等修改數據的語句需手動執行connection.commit()完成對數據修改的提交。sql

獲取自增 ID

cursor.lastrowid

查詢數據

# 執行查詢 SQL
cursor.execute('SELECT * FROM `users`')

# 獲取單條數據
cursor.fetchone()

# 獲取前N條數據
cursor.fetchmany(3)

# 獲取全部數據
cursor.fetchall()

遊標控制

全部的數據查詢操做均基於遊標,咱們能夠經過cursor.scroll(num, mode)控制遊標的位置。數據庫

cursor.scroll(1, mode='relative') # 相對當前位置移動
cursor.scroll(2, mode='absolute') # 相對絕對位置移動

設置遊標類型

查詢時,默認返回的數據類型爲元組,能夠自定義設置返回類型。支持5種遊標類型:segmentfault

  • Cursor: 默認,元組類型
  • DictCursor: 字典類型
  • DictCursorMixin: 支持自定義的遊標類型,需先自定義纔可以使用
  • SSCursor: 無緩衝元組類型
  • SSDictCursor: 無緩衝字典類型

無緩衝遊標類型,適用於數據量很大,一次性返回太慢,或者服務端帶寬較小時。源碼註釋:安全

Unbuffered Cursor, mainly useful for queries that return a lot of data, or for connections to remote servers over a slow network.

Instead of copying every row of data into a buffer, this will fetch rows as needed. The upside of this is the client uses much less memory, and rows are returned much faster when traveling over a slow network
or if the result set is very big.服務器

There are limitations, though. The MySQL protocol doesn't support returning the total number of rows, so the only way to tell how many rows there are is to iterate over every row returned. Also, it currently isn't possible to scroll backwards, as only the current row is held in memory.

建立鏈接時,經過 cursorclass 參數指定類型:

connection = pymysql.connect(host='localhost',
                             user='root',
                             password='root',
                             db='demo',
                             charset='utf8',
                             cursorclass=pymysql.cursors.DictCursor)

也能夠在建立遊標時指定類型:

cursor = connection.cursor(cursor=pymysql.cursors.DictCursor)

事務處理

  • 開啓事務

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),
    ])

參考資料


原文地址: https://shockerli.net/post/py...
更多文章請訪問個人我的博客: https://shockerli.net
相關文章
相關標籤/搜索