任何應用都離不開數據,所以在學習python的時候,當然也要學習一個如何用python操作數據庫了。MySQLdb就是python對mysql數據庫操作的模塊。官方Introduction : MySQLdb is an thread-compatible interface to the popular MySQL database server that provides the Python database API. 它其實相當於翻譯了對應C的接口。
使用這種數據庫接口大多是就是執行連接數據庫->執行query->提取數據->關閉連接 這幾個步驟。MySQLdb提供比較關鍵的對象,分別是Connection、Cursor、Result。具體使用步驟很簡單先不寫了,先寫一些個人認爲比較重要、值得注意的地方。
1、雖然在MySQLdb.Connect(host ,user , passw , db)函數中,我們經常使用的只是這幾個參數,但是其實裏面還有很多比如字符集、線程安全、ssl等也都是很重要的參數,使用時要身份注意。
2、當使用Connection.query()函數進行query後,connection 對象可以返回兩種result,分別是store_result和use_result,store_result 將結果集存回client端,而use_result則是結果集保存在server端,並且維護了一個連接,會佔用server資源。此時,不可以進行任何其他的查詢。建議使用store_result,除非返回結果集(result set)過大或是無法使用limit的情形。
3、提取(fetch)數據的返回形式大多有三種情形。 as a tuple(how=0) ;as dictionaries, key=column or table.column if duplicated(how=1);as dictionaries, key=table.column (how=2)
4、每次fetch,在result內部都會產生數據位置的移動,也就是說假如有10行數據,執行result.fetch_row(3,0),會得到前三行,再執行result.fetch_row(3,0),則會得到中間的三行,所以說fetch會導致position的移動。另外值得注意的是,如果使用use_result,也就是數據存儲在server時,在fetch所有的條目之前,不能進行任何的query操作。
5、mysql本身不支持遊標(Cursor),但是MySQLdb對Cursor進行了仿真。重要的執行query方法有execute 和 executemany 。execute方法,執行單條sql語句,調用executemany方法很好用,數據庫性能瓶頸很大一部分就在於網絡IO和磁盤IO將多個insert放在一起,只執行一次IO,可以有效的提升數據庫性能。遊標cursor具有fetchone、fetchmany、fetchall三個方法提取數據,每個方法都會導致遊標遊動,所以必須關注遊標的位置。遊標的scroll(value, mode)方法可以使得遊標進行卷動,mode參數指定相對當前位置(relative)還是以絕對位置(absolute)進行移動。
6、MySQLdb提供了很多函數方法,在官方指南里沒有完全羅列,使用者可以用help去看看,裏面提供了很多方便的東西。
7、對於mysql來說,如果使用支持事務的存儲引擎,那麼每次操作後,commit是必須的,否則不會真正寫入數據庫,對應rollback可以進行相應的回滾,但是commit後是無法再rollback的。commit() 可以在執行很多sql指令後再一次調用,這樣可以適當提升性能。
8、executemany處理過多的命令也不見得一定好,因爲數據一起傳入到server端,可能會造成server端的buffer溢出,而一次數據量過大,也有可能產生一些意想不到的麻煩。合理,分批次executemany是個不錯的辦法。
最後,我自己寫了個pyMysql模塊,主要是對MySQLdb提供的常用方法進行了簡單的再次封裝,也藉此機會好好學習下MySQLdb,以及練習python的編碼。該程序使用的數據庫表,採用myisam引擎,所以沒加上commit(),一般最好還是要加上的。
代碼如下:PyMysql.py
#-*-
encoding:gb2312 -*-_ ''' Created
on 2012-1-12 @author:
xiaojay ''' import MySQLdb import MySQLdb.cursors STORE_RESULT_MODE
= 0 USE_RESULT_MODE
= 1 CURSOR_MODE
= 0 DICTCURSOR_MODE
= 1 SSCURSOR_MODE
= 2 SSDICTCURSOR_MODE
= 3 FETCH_ONE
= 0 FETCH_MANY
= 1 FETCH_ALL
= 2 class PyMysql: def __init__( self ): self .conn
= None pass def newConnection( self ,host,user,passwd,defaultdb): """ 建立一個新連接,指定host、用戶名、密碼、默認數據庫 """ self .conn
= MySQLdb.Connect(host,user,passwd,defaultdb) if self .conn. open = = False : raise None def closeConnnection( self ): """ 關閉當前連接 """ self .conn.close() def query( self ,sqltext,mode = STORE_RESULT_MODE): """ 作用:使用connection對象的query方法,並返回一個元組(影響行數(int),結果集(result)) 參數:sqltext:sql語句 mode=STORE_RESULT_MODE(0)
表示返回store_result,mode=USESTORE_RESULT_MODE(1) 表示返回use_result 返回:元組(影響行數(int),結果集(result) """ if self .conn = = None or self .conn. open = = False : return - 1 self .conn.query(sqltext) if mode
= = 0 : result
= self .conn.store_result()
elif mode
= = 1 : result
= self .conn.use_result() else : raise Exception( "mode
value is wrong." ) return ( self .conn.affected_rows(),result) def fetch_queryresult( self ,result,maxrows = 1 ,how = 0 ,moreinfo = False ): """ 參數:result:
query後的結果集合 maxrows:
返回的最大行數 how:
以何種方式存儲結果 (0:tuple,1:dictionaries
with columnname,2:dictionaries with table.columnname) moreinfo
表示是否獲取更多額外信息(num_fields,num_rows,num_fields) 返回:元組(數據集,附加信息(當moreinfo=False)或單一數據集(當moreinfo=True) """ if result
= = None :
return None dataset
= result.fetch_row(maxrows,how) if moreinfo
is False : return dataset else : num_fields
= result.num_fields() num_rows
= result.num_rows() field_flags
= result.field_flags() info
= (num_fields,num_rows,field_flags) return (dataset,info) def execute( self ,sqltext,args = None ,mode = CURSOR_MODE,many = False ): """ 作用:使用遊標(cursor)的execute
執行query 參數:sqltext:
表示sql語句 args:
sqltext的參數 mode:以何種方式返回數據集 CURSOR_MODE
= 0 :store_result , tuple DICTCURSOR_MODE
= 1 : store_result , dict SSCURSOR_MODE
= 2 : use_result , tuple SSDICTCURSOR_MODE
= 3 : use_result , dict many:是否執行多行操作(executemany) 返回:元組(影響行數(int),遊標(Cursor)) """ if mode
= = CURSOR_MODE
: curclass
= MySQLdb.cursors.Cursor elif mode
= = DICTCURSOR_MODE
: curclass
= MySQLdb.cursors.DictCursor elif mode
= = SSCURSOR_MODE
: curclass
= MySQLdb.cursors.SSCursor elif mode
= = SSDICTCURSOR_MODE
: curclass
= MySQLdb.cursors.SSDictCursor else : raise Exception( "mode
value is wrong" ) cur
= self .conn.cursor(cursorclass = curclass) line
= 0 if many
= = False : if args
= = None :
line
= cur.execute(sqltext) else : line
= cur.execute(sqltext,args) else : if args
= = None : line
= cur.executemany(sqltext) else : line
= cur.executemany(sqltext,args) return (line
, cur ) def fetch_executeresult( self ,cursor,mode = FETCH_ONE,rows = 1 ): """ 作用:提取cursor獲取的數據集 參數:cursor:遊標 mode:執行提取模式 FETCH_ONE:
提取一個; FETCH_MANY :提取rows個 ;FETCH_ALL : 提取所有 rows:提取行數 返回:fetch數據集 """ if cursor
= = None :
return if mode
= = FETCH_ONE
: return cursor.fetchone() elif mode
= = FETCH_MANY
: return cursor.fetchmany(rows) elif mode
= = FETCH_ALL
: return cursor.fetchall() if __name__ = = "__main__" : print help (PyMysql) |
測試代碼:
#-*-
encoding:gb2312 -*- import PyMysql """ authors
這張表很簡單。 +--------------+-------------+------+-----+---------+----------------+ |
Field | Type | Null | Key | Default | Extra | +--------------+-------------+------+-----+---------+----------------+ |
author_id | int(11) | NO | PRI | NULL | auto_increment | |
author_last | varchar(50) | YES | | NULL | | |
author_first | varchar(50) | YES | MUL | NULL | | |
country | varchar(50) | YES | | NULL | | +--------------+-------------+------+-----+---------+----------------+ 本文主要的所有操作都針對該表。 """ def printAuthors(res,mode = 0 ,lines = 0 ): """ 格式化輸出 """ print "*" * 20 ,
"
lines: " ,lines
, "
" , "*" * 20 if mode = = 0 : for author_id
, author_last , author_first , country in res
: print "ID
: %s , Author_last : %s , Author_First : %s , Country : %s" \ % (author_id
, author_last , author_first , country ) else : for item
in res
: print "-----------" for key
in item.keys(): print key
, "
: " ,item[key] #建立連接 mysql
= PyMysql.PyMysql() mysql.newConnection( host = "localhost" ,
user = "root" ,
passwd = "peterbbs" ,
defaultdb = "bookstore" ) "" #定義sql語句 sqltext
= "select
* from authors order by author_id " #調用query方法,得到result lines
, res = mysql.query(sqltext,
mode = PyMysql.STORE_RESULT_MODE) #提取數據 data
= mysql.fetch_queryresult(res,
maxrows = 20 ,
how = 0 ,
moreinfo = False ) #打印 printAuthors(data, 0 ,lines) #演示多行插入 sqltext
= "insert
into authors (author_last,author_first,country) values (%s,%s,%s)" args
= [( 'aaaaaa' , 'bbbbbb' , 'cccccc' ),( 'dddddd' , 'eeeeee' , 'ffffff' ),( 'gggggg' , 'hhhhhh' , 'iiiiii' )] lines
,cur = mysql.execute(sqltext,args,mode = PyMysql.DICTCURSOR_MODE,many = True ) print "*" * 20 ,
lines , "行被插入
" , "*" * 20 sqltext
= "select
* from authors order by author_id " #調用cursor.execute方法,得到result lines
,cur = mysql.execute(sqltext,mode = PyMysql.DICTCURSOR_MODE) #提取數據 data
= mysql.fetch_executeresult(cur,
mode = PyMysql.FETCH_MANY,
rows = 20 ) #打印 printAuthors(data, 1 ,lines) #關閉連接 mysql.closeConnnection() |
測試輸出:
******************** lines: 5 ********************
ID : 1 , Author_last : Greene , Author_First : Graham , Country : United Kingdom
ID : 4 , Author_last : Peter , Author_First : David , Country : China
ID : 5 , Author_last : mayday , Author_First : Feng , Country : France
ID : 6 , Author_last : zhang , Author_First : lixin , Country : France
ID : 9 , Author_last : zhang111 , Author_First : lixin , Country : France
******************** 3 行被插入 ********************
******************** lines: 8 ********************
-----------
country : United Kingdom
author_id : 1
author_first : Graham
author_last : Greene
-----------
country : China
author_id : 4
author_first : David
author_last : Peter
-----------
country : France
author_id : 5
author_first : Feng
author_last : mayday
-----------
country : France
author_id : 6
author_first : lixin
author_last : zhang
-----------
country : France
author_id : 9
author_first : lixin
author_last : zhang111
-----------
country : cccccc
author_id : 53
author_first : bbbbbb
author_last : aaaaaa
-----------
country : ffffff
author_id : 54
author_first : eeeeee
author_last : dddddd
-----------
country : iiiiii
author_id : 55
author_first : hhhhhh
author_last : gggggg