數據庫接口 / DB-API
在Python中,數據庫是通過適配器(Adaptor)來連接訪問數據庫的,適配器通常與數據庫客戶端接口(通常為C語言編寫)想連接,而不同的適配器都會盡量滿足相同的DB-API標准。
為了保證不同數據庫的數據庫接口能夠通用於適配器,以減少使用不同數據庫接口是需要對代碼進行大幅改動,Python的DB-SIG(數據庫特殊興趣小組)制定了DB-API的標准,該API為不同的關系數據庫提供了一致的接口,使得使用不同數據庫的代碼間移植變得更加簡單。數據庫接口目前的版本為DB-API(2.0),可前往Python官網查看最新版本。
通用標准 / General Standard
對於任意的數據庫適配器db,需要提供至少以下幾項通用標准,以保證可移植性。
1 屬性 / Attribute
1.1 apilevel屬性
屬性調用: al = db.apilevel
屬性功能: 返回當前適配器支持的DB-API版本
屬性參數: al
al: str類型,目前支持"1.0"和"2.0"兩種,如果該適配器未指定,則假定為"1.0"
1.2 threadsafety屬性
屬性調用: tsf = db.threadsafety
屬性功能: 返回當前適配器支持的線程安全等級
屬性參數: tsf
tsf: int類型,線程安全等級
threadsafety |
Meaning |
0 |
Threads may not share the module. |
1 |
Threads may share the module, but not connections. |
2 |
Threads may share the module and connections. |
3 |
Threads may share the module, connections and cursors. |
1.3 paramstyle屬性
屬性調用: psy = db.paramstyle
屬性功能: 返回當前適配器支持的參數風格
屬性參數: psy
psy: str類型,參數風格的說明
paramstyle |
Meaning |
qmark |
Question mark style, e.g. ...WHERE name=? |
numeric |
Numeric, positional style, e.g. ...WHERE name=:1 |
named |
Named style, e.g. ...WHERE name=:name |
format |
ANSI C printf format codes, e.g. ...WHERE name=%s |
pyformat |
Python extended format codes, e.g. ...WHERE name=%(name)s |
2 函數 / Function
2.1 connect ()函數
函數調用: cnx = db.connect/Connection/Connect(*args, **kwargs)
函數功能:生成一個數據庫的連接對象
傳入參數: args, kwargs
host: str類型,連接的主機地址,未傳入或‘localhost’都將連接本地數據庫
user: str類型,登入數據庫的用戶名
password/passwd: str類型,登錄數據庫的密碼
database/db: str類型,使用的數據庫schema名稱
返回參數: cnx
cnx: obj類型,一個數據庫連接實例
3 類 / Class
3.1 Connection類
類實例化:cnx = db.connect/Connection/Connect(*args, **kwargs)
類的功能:用於聯系數據庫API的連接對象
傳入參數: args, kwargs
host: str類型,連接的主機地址,未傳入或‘localhost’都將連接本地數據庫
user: str類型,登入數據庫的用戶名
password/passwd: str類型,登錄數據庫的密碼
database/db: str類型,使用的數據庫schema名稱
返回參數: cnx
cnx: obj類型,一個數據庫連接實例
3.1.1 close()方法
函數調用: cnx.close()
函數功能:關閉數據庫連接
傳入參數: 無
返回參數: 無
3.1.2 commit()方法
函數調用: cnx.commit()
函數功能:提交當前事務,通常當命令具有執行修改等性質的時候需要此函數完成確認
傳入參數: 無
返回參數: 無
3.1.3 rollback()方法
函數調用: cnx.rollback()
函數功能:取消當前事務
傳入參數: 無
返回參數: 無
3.1.4 cursor()方法
函數調用: cur = cnx.cursor()
函數功能:使用該連接對象創建返回一個游標對象
傳入參數: 無
返回參數: cur
cur: obj類型,游標對象的實例,可以通過游標進行操作數據庫
3.2 Cursor類
類實例化:cur = cnx.cursor()
類的功能:一個用於操作數據庫的游標對象
傳入參數: args, kwargs
host: str類型,連接的主機地址,未傳入或‘localhost’都將連接本地數據庫
user: str類型,登入數據庫的用戶名
password/passwd: str類型,登錄數據庫的密碼
database/db: str類型,使用的數據庫schema名稱
返回參數: cnx
cnx: obj類型,一個數據庫連接實例
3.2.1 arraysize屬性
屬性調用: as = cur.arraysize
屬性功能: 表示使用fetchmany()方法時,一次性取出的結果行數,默認為1
屬性參數: as
as: int類型,一次性fetch的行數
3.2.2 connection屬性
屬性調用: cnx = cur.connection
屬性功能: 返回生成該游標的connection實例
屬性參數: cnx
cnx: obj類型,生成當前游標的連接實例
3.2.3 description屬性
屬性調用: dsp = cur.description
屬性功能: 返回當前游標的活動狀態
屬性參數: dsp
dsp: tuple/NoneType類型,一個7元素元組描述當前狀態
3.2.4 lastrowid屬性
屬性調用: rid = cur.lastrowid
屬性功能: 上次修改行的ID,不支持則返回None
屬性參數: rid
rid: int/NoneType類型,修改的行ID
3.2.5 rowcount屬性
屬性調用: roc = cur.rowcount
屬性功能: 上次execute*()修改行所影響的行數
屬性參數: roc
roc: int類型,修改影響的行數
3.2.6 close()方法
函數調用: cur.close()
函數功能:關閉游標
傳入參數: 無
返回參數: 無
3.2.7 execute()方法
函數調用: [r =] cur.execute(query, args=None)
函數功能:執行數據庫命令
傳入參數: query, args
query: str類型,執行的SQL命令行
args: sequence/mapping類型,query使用的參數
返回參數: r
r: int類型,執行所影響的行數
3.2.8 executemany()方法
函數調用: [r =] cur.executemany(query, args)
函數功能:執行多條數據庫命令,類似execute()和map()的結合
傳入參數: query, args
query: str類型,執行的SQL命令行
args: sequence/mapping類型,query使用的參數
返回參數: r
r: int類型,執行所影響的行數
3.2.9 fetchone()方法
函數調用: r = cur.fetchone()
函數功能:獲取查詢結果的下一行
傳入參數: 無
返回參數: r
r: tuple類型,查詢結果的下一條信息的元組
3.2.10 fetchmany()方法
函數調用: r = cur.fetchmany(size=cursor.arraysize)
函數功能:獲取查詢結果的下n行,默認為arraysize的設置值
傳入參數: size
size: int類型,查詢下n行
返回參數: r
r: tuple類型,查詢結果的下n條信息的元組
3.2.11 fetchall()方法
函數調用: r = cur.fetchall()
函數功能:獲取查詢結果的所有(剩余)行
傳入參數: 無
返回參數: r
r: tuple類型,查詢結果的所有剩余信息元組
4 補充知識 / Complement Knowledge
4.1 Cursor與Connection
在MySQL中,Connection生成的實例利用query函數已經可以完成基本的SQL數據庫操作,而Cursor的execute功能與其類似,但是引入Cursor可以使在不必要的時候銷毀Cursor節省資源占用,同時無需斷開連接。參考 stack overflow 鏈接。
5 應用實例 / Complement Knowledge
下面的例子中將構建一個簡單的通用適配器驅動,其中實現了各種適配器通用的函數方法。
1 class SqlConnector(): 2 def __init__(self, adaptor): 3 self.adaptor = adaptor 4 self.result = None 5 # Check Adaptor info 6 print('Adaptor %s apply DB-API %s, thread safety: %d, parameter style: %s' % (adaptor.__name__, adaptor.apilevel, adaptor.threadsafety, adaptor.paramstyle)) 7 8 # Login by user name and password 9 def login(self, **kwargs): 10 # Create a connection obj 11 self.cnx = self.adaptor.connect(**kwargs) 12 13 def logoff(self): 14 self.cnx.close() 15 16 def query_sql(self, sql, show=True): 17 # Method one: Use Connection 18 ''' 19 self.cnx.query(sql) 20 self.result = self.cnx.store_result() 21 r = self.result.fetch_row(0, ) 22 self.cnx.commit() 23 ''' 24 # Method two: Use Cursor 25 cur = self.cnx.cursor() 26 cur.execute(sql) 27 r = cur.fetchall() 28 self.cnx.commit() 29 cur.close() 30 31 if show: 32 splt = '\n' + ((len(sql)+6)*'-') 33 msg = ''.join(('\n{: ^10} | ').format(str(i)) if x.index(i) == 0 else ('{: ^10} | ').format(str(i)) for x in r for i in x) 34 s = ('{:-^%d}'%(len(sql)+6)).format(sql) + msg + splt 35 print(s) 36 return (i for x in r for i in x) 37 38 def exec_sql(self, sql): 39 cur = self.cnx.cursor() 40 cur.execute(sql) 41 self.cnx.commit() 42 cur.close() 43 44 def commit(self): 45 self.cnx.commit() 46 47 if __name__ == '__main__': 48 import MySQLdb 49 import pymssql 50 r = input('Please choose your adaptor:\n(M)MySQL\n(S)MsSQL\n') 51 adaptor_list = {'M': MySQLdb, 'S': pymssql} 52 c = SqlConnector(adaptor_list[r.upper()]) 53 # No local MSSQL server 54 c.login(host='localhost', user='root', password='root') 55 c.logoff()
第 1-6 行,建立適配器的類,在初始化用利用適配器的通用屬性查看適配器的基本信息,包括適配器名稱,使用的DB-API等級,線程安全等級,參數風格等。
第 8-14 行,定義登錄退出函數,登錄時創建連接實例,退出時關閉。
第 16-36 行,定義請求函數,對於數據庫的操作有兩種方式實現,第一種是使用Connection,第二種是使用Cursor,同時對請求的結果進行顯示。
第 38-45 行,定義執行函數,用於執行SQL的命令語句,對於有修改性質的語句必須commit后才能在數據庫端生效。
第 47-55 行,最后僅對數據庫進行登錄退出測試,由於本地僅安裝了MYSQL,沒有安裝MSSQL的服務器,因此無法登錄MSSQL。
運行結果如下
Please choose your adaptor:
(M)MySQL
(S)MsSQL
M
Adaptor MySQLdb apply DB-API 2.0, thread safety: 1, parameter style: format
參考鏈接