python操作MySQL數據庫


MySQLdb呢,其實和Python內置的sqlite3的使用方法基本相同。

警告:

    不要使用字符串拼接生成SQL語句,否則可能產生SQL注入的問題。應當使用 execute() 的第二個參數檢查輸入的合法性。

#do NOT do this!
cmd = "update people set name='%s' where id='%s'" % (name, id) 
cur.execute(cmd)
# instead, do this: cmd = "update people set name=%s where id=%s"
cur.execute(cmd, (name, id))

 

 

采用的是MySQLdb操作的MYSQL數據庫。先來一個簡單的例子吧:

import MySQLdb
 
try:
    conn=MySQLdb.connect(host='localhost',user='root',passwd='mysql',db='test',port=3306)
    cur=conn.cursor()
    cur.execute('select * from user')
    cur.close()
    conn.close()
except MySQLdb.Error,e:
     print "Mysql Error %d: %s" % (e.args[0], e.args[1])

請注意修改你的數據庫,主機名,用戶名,密碼。

下面來大致演示一下插入數據,批量插入數據,更新數據的例子吧:

import MySQLdb
 
try:
    conn=MySQLdb.connect(host='localhost',user='root',passwd='root',port=3306)
    cur=conn.cursor()
     
    cur.execute('create database if not exists python')
    conn.select_db('python')
    cur.execute('create table test(id int,info varchar(20))')
     
    value=[1,'hi rollen']
    cur.execute('insert into test values(%s,%s)',value)
     
    values=[]
    for i in range(20):
        values.append((i,'hi rollen'+str(i)))
         
    cur.executemany('insert into test values(%s,%s)',values)
 
    cur.execute('update test set info="I am rollen" where id=3')
 
    conn.commit()
    cur.close()
    conn.close()
 
except MySQLdb.Error,e:
     print "Mysql Error %d: %s" % (e.args[0], e.args[1])

 

游標相當於是集合中元素的指針,SQL查詢結果是一個集合,而線程每次只能獲得一個元素的引用。游標也必須要關閉,否則會占用有限的資源

有些界面可以自動提交。但是對於python的MySQLdb模塊,必須要調用commit(), 否則所有的更新只對於當前連接有效,數據庫並不會實際被更改。

每插入一次就要commit一次! 具體見本文最后。

 

import MySQLdb
 
try:
    conn=MySQLdb.connect(host='localhost',user='root',passwd='root',port=3306)
    cur=conn.cursor()
     
    conn.select_db('python')
 
    count=cur.execute('select * from test')
    print 'there has %s rows record' % count
 
    result=cur.fetchone()
    print result
    print 'ID: %s info %s' % result
 
    results=cur.fetchmany(5)
    for r in results:
        print r
 
    print '=='*10
    cur.scroll(0,mode='absolute')
 
    results=cur.fetchall()
    for r in results:
        print r[1]
     
 
    conn.commit()
    cur.close()
    conn.close()
 
except MySQLdb.Error,e:
     print "Mysql Error %d: %s" % (e.args[0], e.args[1])

查詢后中文會正確顯示,但在數據庫中卻是亂碼的。

網上的說法是加一個屬性,不過經過本人實驗,這並不能解決問題,反而讓打印出來的中文全是問號。

在Python代碼 

conn = MySQLdb.Connect(host='localhost', user='root', passwd='root', db='python') 中加一個屬性:
 改為:
conn = MySQLdb.Connect(host='localhost', user='root', passwd='root', db='python',charset='utf8') 
charset是要跟你數據庫的編碼一樣,如果是數據庫是gb2312 ,則寫charset='gb2312'。

 

常用函數

下面貼一下常用的函數:

然后,這個連接對象也提供了對事務操作的支持,標准的方法
commit() 提交
rollback() 回滾

cursor用來執行命令的方法:
callproc(self, procname, args):用來執行存儲過程,接收的參數為存儲過程名和參數列表,返回值為受影響的行數
execute(self, query, args):執行單條sql語句,接收的參數為sql語句本身和使用的參數列表,返回值為受影響的行數
executemany(self, query, args):執行單挑sql語句,但是重復執行參數列表里的參數,返回值為受影響的行數
nextset(self):移動到下一個結果集

cursor用來接收返回值的方法:
fetchall(self):接收全部的返回結果行.
fetchmany(self, size=None):接收size條返回結果行.如果size的值大於返回的結果行的數量,則會返回cursor.arraysize條數據.
fetchone(self):返回一條結果行.
scroll(self, value, mode='relative'):移動指針到某一行.如果mode='relative',則表示從當前所在行移動value條,如果 mode='absolute',則表示從結果集的第一行移動value條.

 

字典而非元組

MySQLdb默認情況下,查詢結果行都是返回tuple,訪問的時候不是很方便,必須按照0,1這樣讀取。

使用sqllite3的時候,可以修改過Connection對象的row_factory屬性,以便使用sqlite3.Row,這樣結果集中的數據行就是字典形式的,可以用字段名訪問,那么MySQLdb中是不是也有這樣的方法呢?MySQLdb中有DictCursor,要做到這點也很簡單,那就是建立數據庫連接是傳遞cusorclass參數,或者在獲取Cursor對象時傳遞cusorclass參數即可:
conn=MySQLdb.connect(host="localhost",user="root",passwd="root",db="test",charset="utf8",cursorclass=MySQLdb.cursors.DictCursor)  
cursor = conn.cursor()  
或者
conn=MySQLdb.connect(host="localhost",user="root",passwd="root",db="test",charset="utf8")  
cursor = conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)  

返回結果就是這樣:

{'name': u'ccc', 'created': 33L}
{'name': u'ddd', 'created': 44L}
{'name': u'zzz', 'created': 1340790602L}

 

 

MySQL中的事務

事務支持

首先要了解到,Innodb支持事務, MyISAM不支持事務。

而且mysql的事務是默認是打開autocommit的,但是我們使用的python庫,mysqldb卻是默認關閉autocommit,所以你需要自己去commit,自己去rollback。

回到問題

任何時候,在執行提交或者回滾操作之前,所有的操作都會被數據庫認為屬於同一個事務,

MySQL事務的默認隔離級別是repeatable read(重復讀),而這卻會引起phantom read(幻想讀)。

幻像讀(phantom read):在同一事務中,同一查詢多次進行時候,由於其他插入操作(insert)的事務提交,導致每次返回不同的結果集。

而innodb為了防止幻讀,會在一個事務中,使所有select的結果保持與第一次select時的snapshot一致,這樣其他事務的插入是不會被感知到的。

所以對於一個只有讀的事務,我們也應該及時提交后再讀,使snapshot刷新。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM