Python操作數據庫之 MySQL
一、安裝Python-MySQLdb模塊
Python-MySQLdb是一個操作數據庫的模塊,Python 通過它對 mysql 數據實現各種操作。
如果要源碼安裝,可以這裏下載: https://pypi.Python.org/pypi/MySQL-Python/
解壓安裝包,進入解壓目錄執行以下命令安裝
python setup.py install
ubuntu 下可以這麽做:
sudo apt-get install build-essential Python-dev libmysqlclient-dev sudo apt-get install Python-MySQLdb
pip安裝:
pip install mysql-Python
安裝之後,在 python 交互模式下:
>>> import MySQLdb
如果不報錯,恭喜你,已經安裝好了。
二、操作數據庫
操作數據庫流程:
1、導入MySQLdb模塊
2、創建數據庫連接
3、執行SQL語句和存儲過程
4、關閉數據庫連接
創建MySQL連接對象
>>> import MySQLdb >>> conn = MySQLdb.connect(host="localhost",user="root",passwd="123456",db="python",port=3306,charset="utf8") >>>
命令含義解釋:
host:等號的後面應該填寫 mysql 數據庫的地址,因為就數據庫就在本機上(也稱作本地),所以使用 localhost,註意引號。如果在其它的服務器上,這裏應該填寫 ip 地址。一般中小型的網站,數據庫和程序都是在同一臺服務器(計算機)上,就使用 localhost 了。
user:登錄數據庫的用戶名,這裏一般填寫"root",還是要註意引號。當然,如果讀者命名了別的用戶名,數據庫管理者提供了專有用戶名,就更改為相應用戶。但是,不同用戶的權限可能不同,所以,在程序中,如果要操作數據庫,還要註意所擁有的權限。在這裏用 root,就放心了,什麽權限都有啦。不過,這樣做,在大型系統中是應該避免的。
passwd:上述 user 賬戶對應的登錄 mysql 的密碼。我在上面的例子中用的密碼是"123123"。不要忘記引號。
db:就是剛剛通 create 命令建立的數據庫,我建立的數據庫名字是"qiwsirtest",還是要註意引號。看官如果建立的數據庫名字不是這個,就寫自己所建數據庫名字。
port:一般情況,mysql 的默認端口是 3306,當 mysql 被安裝到服務器之後,為了能夠允許網絡訪問,服務器(計算機)要提供一個訪問端口給它。
charset:這個設置,在很多教程中都不寫,結果在真正進行數據存儲的時候,發現有亂碼。這裏我將 qiwsirtest 這個數據庫的編碼設置為 utf-8 格式,這樣就允許存入漢字而無亂碼了。註意,在 mysql 設置中,utf-8 寫成 utf8,沒有中間的橫線。但是在 Python 文件開頭和其它地方設置編碼格式的時候,要寫成 utf-8。切記!
Python 建立了與數據的連接,其實是建立了一個 MySQLdb.connect() 的實例對象,或者泛泛地稱之為連接對象,Python 就是通過連接對象和數據庫對話。這個對象常用的方法有:
commit():如果數據庫表進行了修改,提交保存當前的數據。當然,如果此用戶沒有權限就作罷了,什麽也不會發生。
rollback():如果有權限,就取消當前的操作,否則報錯。
cursor([cursorclass]):返回連接的遊標對象。通過遊標執行 SQL 查詢並檢查結果。遊標比連接支持更多的方法,而且可能在程序中更好用。
close():關閉連接。此後,連接對象和遊標都不再可用了。
創建遊標
Python 和數據之間的連接建立起來之後,要操作數據庫,就需要讓 Python 對數據庫執行 SQL 語句。Python 是通過遊標執行 SQL 語句的。所以,連接建立之後,就要利用連接對象得到遊標對象,方法如下:
>>> cur = conn.cursor()
此後,就可以利用遊標對象的方法對數據庫進行操作。那麽還得了解遊標對象的常用方法:
名稱 | 描述 |
close() | 關閉遊標。之後遊標不可用 |
execute(query[,args]) | 執行一條 SQL 語句,可以帶參數 |
executemany(query, pseq) | 對序列 pseq 中的每個參數執行 sql 語句 |
fetchone() | 返回一條查詢結果 |
fetchall() | 返回所有查詢結果 |
fetchmany([size]) | 返回 size 條結果 |
nextset() | 移動到下一個結果 |
scroll(value,mode='relative') | 移動遊標到指定行,如果 mode='relative',則表示從當前所在行移動 value 條,如果 mode='absolute',則表示從結果集的第一行移動 value 條 |
插入數據
>>> cur.execute("insert into user (name,age,mail) values (%s,%s,%s)",("lulu",18,"[email protected]")) 1L >>>
沒有報錯,並且返回一個"1L"結果,說明有一n 行記錄操作成功。
登錄MySQL,驗證數據有沒有添加成功
mysql> select * from user; Empty set (0.00 sec) mysql>
奇怪,並沒有看到插入的那條數據!到底哪裏錯了
特別註意,通過"cur.execute()"對數據庫進行操作之後,沒有報錯,完全正確,但是不等於數據就已經提交到數據庫中了,還必須要用到"MySQLdb.connect"連接對象的一個方法:commit(),將數據提交上去,也就是進行了"cur.execute()"操作,要將數據提交,必須執行:
>>> conn.commit()
再次登錄MySQL,看數據有沒有添加成功
mysql> select * from user; +----+------+------+----------------+ | id | name | age | mail | +----+------+------+----------------+ | 1 | lulu | 18 | [email protected] | +----+------+------+----------------+ 1 row in set (0.00 sec) mysql>
果然如此。這就如同編寫一個文本一樣,將文字寫到文本上,並不等於文字已經保留在文本文件中了,必須執行"CTRL-S"才能保存。也就是在通過 Python 操作數據庫的時候,以"execute()"執行各種 sql 語句之後,要讓已經執行的效果保存,必須運行連接對象的"commit()"方法。
插入多條數據
>>> cur.executemany("insert into user (name,age,mail) values (%s,%s,%s)",(("google",25,"[email protected]"),("facebook",18,"[email protected]"),("github",20,"[email protected]"),("docker",10,"[email protected]"))) 4L >>>
mysql> select * from user; +----+----------+------+----------------+ | id | name | age | mail | +----+----------+------+----------------+ | 1 | lulu | 18 | [email protected] | | 2 | google | 25 | [email protected] | | 3 | facebook | 18 | [email protected] | | 4 | github | 20 | [email protected] | | 5 | docker | 10 | [email protected] | +----+----------+------+----------------+ 5 rows in set (0.00 sec) mysql>
成功插入了多條記錄。在"executemany(query, pseq)"中,query 還是一條 sql 語句,但是 pseq 這時候是一個 tuple,這個 tuple 裏面的元素也是 tuple,每個 tuple 分別對應 sql 語句中的字段列表。這句話其實被執行多次。只不過執行過程不顯示給我們看罷了。
查詢
如果要從數據庫中查詢數據,也用遊標方法來操作了。
>>> cur.execute("select * from user") 5L >>> print cur.fetchall() ((1L, u'lulu', 18L, u'[email protected]'), (2L, u'google', 25L, u'[email protected]'), (3L, u'facebook', 18L, u'[email protected]'), (4L, u'github', 20L, u'[email protected]'), (5L, u'docker', 10L, u'[email protected]')) >>>
用cur.execute() 從數據庫查詢出來的東西,被“保存在了 cur 所能找到的某個地方”,要找出這些被保存的東西,需要用cur.fetchall()(或者 fechone 等),並且找出來之後,做為對象存在。從上面的實驗探討發現,被保存的對象是一個 tuple 中,裏面的每個元素,都是一個一個的 tuple。因此,用 for 循環就可以一個一個拿出來了。
再次執行一次上面的操作
>>> print cur.fetchall() () >>>
為什麽結果是空的?
原來是通過遊標找出來的對象,在讀取的時候有一個特點,就是那個遊標會移動。在第一次操作了 print cur.fetchall() 後,因為是將所有的都打印出來,遊標就從第一條移動到最後一條。當 print 結束之後,遊標已經在最後一條的後面了。接下來如果再次打印,就空了,最後一條後面沒有東西了。
再看一個實驗
>>> cur.execute("select * from user") 5L >>> print cur.fetchone() (1L, u'lulu', 18L, u'[email protected]') >>> print cur.fetchone() (2L, u'google', 25L, u'[email protected]') >>> print cur.fetchone() (3L, u'facebook', 18L, u'[email protected]') >>> print cur.fetchone() (4L, u'github', 20L, u'[email protected]') >>> print cur.fetchone() (5L, u'docker', 10L, u'[email protected]') >>>
這次不一次全部打印出來了,而是一次打印一條,可以從結果中看出來,果然那個遊標在一條一條向下移動
既然在操作存儲在內存中的對象時候,遊標會移動,能不能讓遊標向上移動,或者移動到指定位置呢?當然可以,這就是scroll()
>>> print cur.fetchone() (5L, u'docker', 10L, u'[email protected]') >>> cur.scroll(-3) >>> print cur.fetchone() (3L, u'facebook', 18L, u'[email protected]') >>> cur.scroll(1) >>> print cur.fetchone() (5L, u'docker', 10L, u'[email protected]')>>>
果然,這個函數能夠移動遊標,不過請仔細觀察,上面的方式是讓遊標相對與當前位置向上或者向下移動。即:
cur.scroll(n),或者,cur.scroll(n,"relative"):意思是相對當前位置向上或者向下移動,n 為正數,表示向下(向前),n 為負數,表示向上(向後)
還有一種方式,可以實現“絕對”移動,不是“相對”移動:增加一個參數"absolute"
特別提醒看官註意的是,在 Python 中,序列對象是的順序是從 0 開始的。
>>> cur.scroll(1,"absolute") 回到序號1,指向第2條數據 >>> print cur.fetchone() (2L, u'google', 25L, u'[email protected]') >>> >>> cur.scroll(0,"absolute") 回到序號0,指向第1條數據 >>> print cur.fetchone() (1L, u'lulu', 18L, u'[email protected]') >>>
承接上面操作,繼續
>>> print cur.fetchmany(3) ((2L, u'google', 25L, u'[email protected]'), (3L, u'facebook', 18L, u'[email protected]'), (4L, u'github', 20L, u'[email protected]')) >>>
上面這個操作,就是實現了從當前位置(遊標指向 tuple 的序號為 1 的位置,即第二條記錄)開始,含當前位置,向下列出 3 條記錄。
更新數據
更新和插入一樣,都需要commit()來提交保存。
>>> cur.execute("update user set name=%s where id=5",("apple",)) 1L >>> cur.execute("select * from user where id=5") 1L >>> print cur.fetchone() (5L, u'apple', 10L, u'[email protected]') >>>
提交更新
>>> conn.commit() >>>
最後,關閉遊標,關閉連接對象
>>> cur.close() >>> conn.close() >>>
Python操作數據庫之 MySQL