最近学习python操作mysql数据库的知识,python访问数据库有自己的统一接口程序:Python DB API。这是我学习的一个小例子。(安装和基本知识可以自行复习:http://blog.csdn.net/xunalove/article/details/76695549)
ubutu 16.04 + python2.7 + mysql 5.7.19
首先要知道使用Python DB API 访问数据库的流程:
开始—->创建connection—->获取cursor—->执行查询, 执行命令, 获取数据, 处理数据—->关闭cursor —->关闭connection—->结束。
模拟银行转账系统的思路:(假设帐号1给账户2转账200元)
我使用的是命令行,当然你也可以使用可视化界面创建,看个人爱好。
我已经创建好了数据库为”test”
使用”use test”进入test数据库,创建数据表” accunt “
mysql> create table accunt(
-> acctid int(11) not null primary key auto_increment,
-> money int(11) not null);
创建两条信息
mysql> insert into accunt values('1','1000');
Query OK, 1 row affected (0.02 sec)
mysql> insert into accunt values('2','500');
Query OK, 1 row affected (0.02 sec)
使用select查看数据表如下
mysql> select * from accunt;
+--------+-------+
| acctid | money |
+--------+-------+
| 1 | 800 |
| 2 | 700 |
+--------+-------+
2 rows in set (0.00 sec)
这里我们使用类的方法来实现功能,首先在脚本执行的入口处用到了argv来传入三个参数:付款人的id, 收款人的id ,转账的钱数。接着调用TransferMoney()类。这里主要有五个方法,先看检查id是否存在的实现:利用select语句从数据库中提取id==付款人的id,通过cursor.fetchall()提取所有数据保存在rs里面(此时是rs保存的是一个列表)列表长度为一则存在,判断金额是否大于200元方法类似。
下面就是执行转账(加减操作)的操作,用到了update方法,需要注意的是判断转账成功的这里用到了cursor.rowcount,它返回的值代表执行update之后数据库中改变的行数。
下面附上完整代码:
# -*- coding:utf-8 -*-
import sys
import MySQLdb
class TransferMoney(object):
def __init__(self, conn):
self.conn = conn
def check_acct_available(self,acctid):
try:
cursor = self.conn.cursor()
sql = "select * from accunt where acctid=%s"%acctid
cursor.execute(sql)
print "check_acct_available:" + sql
rs = cursor.fetchall()
if len(rs)!=1:
raise Exception("帐号%s不存在"% acctid)
finally:
cursor.close()
def has_enough_money(self,acctid, money):
try:
cursor = self.conn.cursor()
sql = "select * from accunt where acctid=%s and money > %s"%(acctid,money)
cursor.execute(sql)
print "has_enough_money:" + sql
rs = cursor.fetchall()
if len(rs)!=1:
raise Exception("帐号%s没有足够的钱"% acctid)
finally:
cursor.close()
def reduce_money(self,acctid,money):
try:
cursor = self.conn.cursor()
sql = "update accunt set money=money-%s where acctid=%s"%(money,acctid)
cursor.execute(sql)
print "reduce_money:" + sql
if cursor.rowcount !=1: #使用rowcount是否影响数据库中的数据
raise Exception("帐号%s减款失败"% acctid)
finally:
cursor.close()
def add_money(self,acctid,money):
try:
cursor = self.conn.cursor()
sql = "update accunt set money=money+%s where acctid=%s"%(money,acctid)
cursor.execute(sql)
print "add_money:" + sql
if cursor.rowcount!=1:
raise Exception("帐号%s加款失败"% acctid)
finally:
cursor.close()
def transfer(self,source_acctid, target_acctid, money):
try:
#检查帐号是否可用
self.check_acct_available(source_acctid)
self.check_acct_available(target_acctid)
#检查付款人是否有足够的money
self.has_enough_money(source_acctid, money)
self.reduce_money(source_acctid,money)
self.add_money(target_acctid,money)
self.conn.commit()
except Exception as e:
self.conn.rollback()
raise e
#脚本执行的入口
if __name__=="__main__":
source_acctid = sys.argv[1] #付款人的id
target_acctid = sys.argv[2] #收款人的id
money = sys.argv[3] #转账的金额
conn = MySQLdb.Connect(host='127.0.0.1',user='root',passwd='root',db='test')
tr_money = TransferMoney(conn)
try:
tr_money.transfer(source_acctid, target_acctid, money)
except Exception as e:
print "出现问题:" + str(e)
finally:
conn.close()
在这里我们需要注意的是每次只需执行操作不论是否抛出异常都是关闭cursor,并且在数据库的最后需要关闭connection对象。其次就是commit的使用,假如我们update,insert,delet操作数据之后没有commit,则不会在数据库中改变数据,应为此时的数据只是作为一个事务,并没有提交和执行。最后就是roll back使用,在进行多操作时,其中一个操作抛出异常,就回滚,则前面进行的操作也是无效的,这里用到了事物的一致性,要么都操作,要么都不操作。。。
已经上传至github,链接:https://github.com/xuna123/Python_pro/tree/master/%E9%A1%B9%E7%9B%AE%E4%B8%83
参考资料:http://www.imooc.com/video/9219