首先祝大家新年快樂哈浇冰!學(xué)生的估計(jì)明天也要上課了贬媒,工作的估計(jì)早就去上班了,我也快要上課了肘习,哈哈际乘,新年這段時(shí)間一直沒有寫過文章,一直忙于跑親戚和學(xué)習(xí)漂佩,感覺有點(diǎn)對(duì)不起關(guān)注我的粉絲脖含。所以,今天決定抽空寫一篇技術(shù)文章來給大家看看投蝉,繼上篇寫了入門mysql之后养葵,還沒有學(xué)習(xí)如何用python來操作數(shù)據(jù)庫,那我今天就帶大家來學(xué)習(xí)如何用python操操作數(shù)據(jù)庫瘩缆。
進(jìn)入正題
工欲善其事关拒,必先利其器。所以第一步,我們先下載第三方庫夏醉。在這里,我用到的是pymysql庫涌韩。
下載庫:在命令行輸入
1pip install pymysql
下載后可檢驗(yàn)一下是否成功下載畔柔。直接在命令行進(jìn)入python然后導(dǎo)庫即可
1C:\Users\June>python2Python 3.6.3 |Anaconda, Inc.| (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] on win323Type "help", "copyright", "credits" or "license" for more information.4>>> import pymysql5>>>
看到這個(gè)畫面就說明下載成功了,接下來學(xué)習(xí)如何操作數(shù)據(jù)庫了3加!0胁痢!
1.連接數(shù)據(jù)庫
1import pymysql2# 連接數(shù)據(jù)庫3db = pymysql.connect(host='127.0.0.1',user='root',passwd='your password',db='news',port=3306,charset='utf8')
以上的參數(shù)是必填的雇毫,
host: 這個(gè)是ip地址玄捕,因?yàn)槲疫@里是本地的,所以填127.0.0.1棚放,也可以填localhost枚粘。
user:用戶名,如果你也是本地的飘蚯,就填root好了
passwd:這個(gè)是密碼馍迄,填上你自己設(shè)的密碼就可以了
db:這個(gè)是數(shù)據(jù)庫名,我這里選的是news數(shù)據(jù)庫
port:這個(gè)是端口局骤,本地的一般都是3306
charset:這個(gè)是編碼方式攀圈,要和你數(shù)據(jù)庫的編碼方式一致,要不會(huì)連接失敗
連接上了峦甩,怎么驗(yàn)證呢赘来?這里我們可以選擇查一條數(shù)據(jù)
1try: 2 db = pymysql.connect(host='127.0.0.1',user='root',passwd='your password',db='news',port=3306,charset='utf8') 3 # 檢驗(yàn)數(shù)據(jù)庫是否連接成功 4 cursor = db.cursor() 5 # 這個(gè)是執(zhí)行sql語句,返回的是影響的條數(shù) 6 data = cursor.execute('SELECT * FROM `new`') 7 # 得到一條數(shù)據(jù) 8 one = cursor.fetchone() 9 print(data)10 print(one)11except pymysql.Error as e:12 print(e)13 print('操作數(shù)據(jù)庫失敗')14finally:15 # 如果連接成功就要關(guān)閉數(shù)據(jù)庫16 if db:17 db.close()
代碼解讀:因?yàn)樵谶B接數(shù)據(jù)庫中凯傲,有時(shí)會(huì)發(fā)生連接失敗等異常犬辰,所以這里就進(jìn)行捕捉異常,這里的異常都是在 pymsql.Error 里面泣洞。上面的代碼看不懂也沒關(guān)系忧风,因?yàn)槲医酉聛頃?huì)說,如果運(yùn)行后有結(jié)果證明連接成功球凰。
在用完后狮腿,一定要記得關(guān)閉數(shù)據(jù)庫連接,防止資源泄露問題呕诉。
2.對(duì)數(shù)據(jù)進(jìn)行查詢
1import pymysql 2try: 3 conn = pymysql.connect(host='127.0.0.1',user='root',passwd='password',db='news',charset='utf8',port=3306) 4 # 這個(gè)是光標(biāo)缘厢,用來操作數(shù)據(jù)庫語句 5 cursor = conn.cursor() 6 # 執(zhí)行sql語句 7 cursor.execute('SELECT * FROM `new`') 8 print(cursor.fetchone()) 9 # 關(guān)閉光標(biāo)10 cursor.close()11except pymysql.Error as e:12 print(e)13 print('操作數(shù)據(jù)庫失敗')14finally:15 if conn:16 conn.close()
代碼解讀:
cursor():這個(gè)是光標(biāo),用來執(zhí)行mysql語句的甩挫,用完后也是需要關(guān)閉的
excute****():這個(gè)是執(zhí)行語句祟敛,執(zhí)行參數(shù)的mysql語句
fetchone():這個(gè)是查看執(zhí)行語句后的一條數(shù)據(jù)
fetchall():這個(gè)是查看所有數(shù)據(jù)
在查詢數(shù)據(jù)后,返回的是一整條數(shù)據(jù)然低,有沒有可以按字典形式來查詢的呢?來試試间护!
1print(cursor.fetchone()['name'])23Traceback (most recent call last):4 File "E:/anaconda/python_project/mysql_test/test2.py", line 8, in <module>5 print(cursor.fetchone()['name'])6TypeError: tuple indices must be integers or slices, not str
查了之后,編譯器想都不想就給了我這個(gè)錯(cuò)誤挖诸,說這是個(gè)元組汁尺,不能這樣操作。
雖然python沒有提供多律,但是我們可以手動(dòng)轉(zhuǎn)成字典來查詢啊
cursor這里有個(gè)屬性:description痴突。獲取的是數(shù)據(jù)庫每個(gè)欄位情況,如下:
1print(cursor.description)2# 下面是結(jié)果3(('id', 3, None, 11, 11, 0, False), ('type', 253, None, 5, 5, 0, False), ('title', 253, None, 50, 50, 0, False), ('content', 253, None, 2000, 2000, 0, False), ('view_count', 3, None, 11, 11, 0, False), ('release_time', 12, None, 19, 19, 0, False), ('author', 253, None, 20, 20, 0, True), ('from', 253, None, 20, 20, 0, True), ('is_valibale', 3, None, 11, 11, 0, False)
所以狼荞,我們利用這個(gè)屬性手動(dòng)生成字典
1# 將一條數(shù)據(jù)轉(zhuǎn)成字典方便查找2new = dict(zip([x[0] for x in cursor.description],[x for x in cursor.fetchone()]))3print(new)4# 下面是結(jié)果5{'id': 2, 'type': 'NBA', 'title': '考辛斯跟腱撕裂賽季報(bào)銷 濃眉詹皇發(fā)聲祝福', 'content': '他遭遇左腳跟腱撕裂辽装,將缺席賽季剩下的比賽。這無疑對(duì)考辛斯和鵜鶘隊(duì)都是一個(gè)重大的打擊', 'view_count': 3560, 'release_time': datetime.datetime(2018, 1, 27, 12, 10), 'author': 'xiaoylin', 'from': '騰訊體育', 'is_valibale': 1}
這里利用zip函數(shù)和列表生成式來一行代碼就生成成功了
用字典來查詢相味,現(xiàn)在就可以了
1print(new['title'])2# 下面是結(jié)果3考辛斯跟腱撕裂賽季報(bào)銷 濃眉詹皇發(fā)聲祝福
但是拾积,上面的只是一條數(shù)據(jù)的,如果是多條的呢攻走?再按上面的方法就行不通了殷勘。這時(shí)就需要用到map函數(shù)了
1def new2dict(new):2 return dict(zip([x[0] for x in cursor.description],[x for x in new]))3news_list = list(map(new2dict,cursor.fetchall()))4print(news_list)5# 下面是結(jié)果6[{'id': 2, 'type': 'NBA', 'title': '考辛斯跟腱撕裂賽季報(bào)銷 濃眉詹皇發(fā)聲祝福', 'content': '他遭遇左腳跟腱撕裂,將缺席賽季剩下的比賽昔搂。這無疑對(duì)考辛斯和鵜鶘隊(duì)都是一個(gè)重大的打擊', 'view_count': 3560, 'release_time': datetime.datetime(2018, 1, 27, 12, 10), 'author': 'xiaoylin', 'from': '騰訊體育', 'is_valibale': 1}, {'id': 3, 'type': 'NBA', 'title': '火箭挖21分大哈登得背鍋 連遭濃眉大帽太尷尬', 'content': '火箭在客場(chǎng)以113-115惜敗于鵜鶘玲销,4連勝終結(jié)。詹姆斯-哈登出戰(zhàn)34分鐘16投5中摘符,其中三分球9投只有1中贤斜,罰球14罰12中,拿到23分逛裤、11助攻瘩绒、5籃板但也有4次失誤,其在場(chǎng)正負(fù)值為尷尬的-12分', 'view_count': 7520, 'release_time': datetime.datetime(2018, 1, 27, 12, 5), 'author': 'youngcao', 'from': '騰訊體育','is_valibale': 1}, {'id': 4, 'type': '英超', 'title': '足總杯-曼聯(lián)4-0英乙球隊(duì)晉級(jí) 桑神首秀造兩球', 'content': '2017-18賽季英格蘭足總杯第4輪带族,曼聯(lián)客場(chǎng)4比0擊敗英乙球隊(duì)約維爾锁荔,順利晉級(jí)下一輪。桑切斯迎來曼聯(lián)首秀蝙砌,并制造了兩個(gè)入球', 'view_count': 6560, 'release_time': datetime.datetime(2018, 1, 27, 5, 49), 'author': 'ricazhang', 'from': '騰訊體育','is_valibale': 1}, {'id': 5, 'type': '英超', 'title': '這才配紅魔7號(hào)阳堕!桑神首秀大腿級(jí)表演 回?fù)魢u聲質(zhì)疑', 'content': '在今天凌晨對(duì)陣約維爾的首秀也值得期待。雖然在登場(chǎng)的72分鐘時(shí)間里沒有進(jìn)球择克,但送出1次助攻且有有6次威脅傳球的數(shù)據(jù)還是十分亮眼', 'view_count': 2760, 'release_time': datetime.datetime(2018, 1, 27, 6, 13), 'author': 'yaxinhao', 'from': '騰訊體育', 'is_valibale': 1}]
這里很巧妙的利用了map函數(shù)恬总,因?yàn)槎鄺l數(shù)據(jù)就可以進(jìn)行迭代了,需要操作每條數(shù)據(jù)肚邢,這樣就可以想到map函數(shù)
接下來我們?cè)儆妹嫦驅(qū)ο蟮姆椒▉碛胮ython進(jìn)行查詢數(shù)據(jù)庫
1import pymysql 2class MysqlSearch(object): 3 def get_conn(self): 4 '''連接mysql數(shù)據(jù)庫''' 5 try: 6 self.conn = pymysql.connect(host='127.0.0.1',user='root',passwd='your password',port=3306,charset='utf8',db='news') 7 except pymysql.Error as e: 8 print(e) 9 print('連接數(shù)據(jù)庫失敗')1011 def close_conn(self):12 '''關(guān)閉數(shù)據(jù)庫'''13 try:14 if self.conn:15 self.conn.close()16 except pymysql.Error as e:17 print(e)18 print('關(guān)閉數(shù)據(jù)庫失敗')1920 def get_one(self):21 '''查詢一條數(shù)據(jù)'''22 try:23 # 這個(gè)是連接數(shù)據(jù)庫24 self.get_conn()25 # 查詢語句26 sql = 'SELECT * FROM `new` WHERE `type`=%s'27 # 這個(gè)光標(biāo)用來執(zhí)行sql語句28 cursor = self.conn.cursor()29 cursor.execute(sql,('英超',))30 new = cursor.fetchone()31 # 返回一個(gè)字典壹堰,讓用戶可以按數(shù)據(jù)類型來獲取數(shù)據(jù)32 new_dict = dict(zip([x[0] for x in cursor.description],new))33 # 關(guān)閉cursor34 cursor.close()35 self.close_conn()36 return new_dict37 except AttributeError as e:38 print(e)39 return None40 def get_all(self):41 '''獲取所有結(jié)果'''42 sql = 'SELECT * FROM `new` '43 self.get_conn()44 try:45 cursor = self.conn.cursor()46 cursor.execute(sql)47 news = cursor.fetchall()48 # 將數(shù)據(jù)轉(zhuǎn)為字典拭卿,讓用戶根據(jù)鍵來查數(shù)據(jù)49 news_list =list(map(lambda x:dict(zip([x[0] for x in cursor.description],[d for d in x])),news))50 # 這樣也行,連續(xù)用兩個(gè)列表生成式51 news_list = [dict(zip([x[0] for x in cursor.description],row)) for row in news]52 cursor.close()53 self.close_conn()54 return news_list55 except AttributeError as e:56 print(e)57 return None5859def main():60 # 獲取一條數(shù)據(jù)61 news = MysqlSearch()62 new = news.get_one()63 if new:64 print(new)65 else:66 print('操作失敗')6768 # 獲取多條數(shù)據(jù)69 news = MysqlSearch()70 rest = news.get_all()71 if rest:72 print(rest)73 print(rest[7]['type'],rest[7]['title'])74 print('類型:{0},標(biāo)題:{1}'.format(rest[12]['type'],rest[12]['title']))75 for row in rest:76 print(row)77 else:78 print('沒有獲取到數(shù)據(jù)')7980if __name__ == '__main__':81 main()
這樣就可以通過實(shí)例的方法來進(jìn)行查詢數(shù)據(jù)庫了
我們還可以根據(jù)頁數(shù)來進(jìn)行查詢指定的數(shù)據(jù)數(shù)
1 def get_more(self,page,page_size): 2 '''查多少頁的多少條數(shù)據(jù)''' 3 offset = (page-1)*page_size 4 sql = 'SELECT * FROM `new` LIMIT %s,%s' 5 try: 6 self.get_conn() 7 cursor = self.conn.cursor() 8 cursor.execute(sql,(offset,page_size,)) 9 news = [dict(zip([x[0] for x in cursor.description],new)) for new in cursor.fetchall()]10 cursor.close()11 self.close_conn()12 return news13 except AttributeError as e:14 print(e)15 return None1617def main():18 #獲取某頁的數(shù)據(jù)19 news = MysqlSearch()20 new = news.get_more(3,5)21 if new:22 for row in new:23 print(row)24 else:25 print('獲取數(shù)據(jù)失敗')2627if __name__ == '__main__':28 main()
利用的是mysql的limit關(guān)鍵字,還有其他的贱纠,比如進(jìn)行排序分組的感興趣的可以自己嘗試下
3.增加數(shù)據(jù)到數(shù)據(jù)庫
1 def add_one(self): 2 sql = 'INSERT INTO `new`(`title`,`content`,`type`,`view_count`,`release_time`) VALUE(%s,%s,%s,%s,%s)' 3 try: 4 self.get_conn() 5 cursor = self.conn.cursor() 6 cursor.execute(sql, ('title', 'content', 'type', '1111', '2018-02-01')) 7 cursor.execute(sql, ('標(biāo)題', '內(nèi)容', '類型', '0000', '2018-02-01')) 8 # 一定需要提交事務(wù)峻厚,要不不會(huì)顯示,只會(huì)占位在數(shù)據(jù)庫 9 self.conn.commit()10 return 111 except AttributeError as e:12 print('Error:', e)13 return 014 except TypeError as e:15 print('Error:', e)16 # 發(fā)生錯(cuò)誤還提交就是把執(zhí)行正確的語句提交上去17 # self.conn.commit()18 # 下面這個(gè)方法是發(fā)生異常就全部不能提交,但語句執(zhí)行成功的就會(huì)占位19 self.conn.rollback()20 return 021 finally:22 cursor.close()23 self.close_conn()2425 def main():26 news = OperateSQL()27 if news.add_one():28 print('增加數(shù)據(jù)成功')29 else:30 print('發(fā)生異常谆焊,請(qǐng)檢查D磕尽!懊渡!')3132 if __name__ == '__main__':33 main()
因?yàn)槭窃黾訑?shù)據(jù),所以需要提交事務(wù)军拟,這就需要用到cursor.commit()來進(jìn)行提交剃执,在增加數(shù)據(jù)后,如果不提交懈息,數(shù)據(jù)庫就不會(huì)顯示肾档。
還有修改數(shù)據(jù)和刪除數(shù)據(jù)就不貼出來了,只是把上面的sql變量的語句改成修改或者刪除的語句就可以了辫继,如果你還不會(huì)怒见,建議練習(xí)下
END
代碼我放在github了,網(wǎng)站為https://github.com/SergioJune/gongzhonghao_code姑宽,有興趣的可以去看看遣耍,如果可以的話希望給個(gè)star哈!
這篇文章只適合入門的炮车,如果需要學(xué)習(xí)更多的話可以去查看pymysql的文檔http://pymysql.readthedocs.io/en/latest/ 舵变。