Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。
Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:
DB-API 是一个规范. 它定义了一系列必须的对象和数据库存取方式, 以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口 。
Python的DB-API,为大多数的数据库实现了接口,使用它连接各数据库后,就可以用相同的方式操作各数据库。
Python DB-API使用流程:
如果执行后的输出结果如下所示,意味着你没有安装 MySQLdb 模块:#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
Traceback (most recent call last):
File "test.py", line 3, in <module>
import MySQLdb
ImportError: No module named MySQLdb
Python使用MySQL的流程:
执行以上脚本输出结果如下:#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 使用execute方法执行SQL语句
cursor.execute("SELECT VERSION()")
# 使用 fetchone() 方法获取一条数据
data = cursor.fetchone()
print "Database version : %s " % data
# 关闭数据库连接
db.close()
Database version : 5.0.45
数据库插入操作#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# 如果数据表已经存在使用 execute() 方法删除表。
cursor.execute("DROP TABLE IF EXISTS EMPLOYEE")
# 创建数据表SQL语句
sql = """CREATE TABLE EMPLOYEE (
FIRST_NAME CHAR(20) NOT NULL,
LAST_NAME CHAR(20),
AGE INT,
SEX CHAR(1),
INCOME FLOAT )"""
cursor.execute(sql)
# 关闭数据库连接
db.close()
以上例子也可以写成如下形式:#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 插入语句
sql = """INSERT INTO EMPLOYEE(FIRST_NAME,
LAST_NAME, AGE, SEX, INCOME)
VALUES ('Mac', 'Mohan', 20, 'M', 2000)"""
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# Rollback in case there is any error
db.rollback()
# 关闭数据库连接
db.close()
实例:#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 插入语句
sql = "INSERT INTO EMPLOYEE(FIRST_NAME, \
LAST_NAME, AGE, SEX, INCOME) \
VALUES ('%s', '%s', '%d', '%c', '%d' )" % \
('Mac', 'Mohan', 20, 'M', 2000)
try:
# 执行sql语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭数据库连接
db.close()
以上脚本执行结果如下:#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 查询语句
sql = "SELECT * FROM EMPLOYEE \
WHERE INCOME > '%d'" % (1000)
try:
# 执行SQL语句
cursor.execute(sql)
# 获取所有记录列表
results = cursor.fetchall()
for row in results:
fname = row[0]
lname = row[1]
age = row[2]
sex = row[3]
income = row[4]
# 打印结果
print "fname=%s,lname=%s,age=%d,sex=%s,income=%d" % \
(fname, lname, age, sex, income )
except:
print "Error: unable to fecth data"
# 关闭数据库连接
db.close()
fname=Mac, lname=Mohan, age=20, sex=M, income=2000
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 更新语句
sql = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = '%c'" % ('M')
try:
# 执行SQL语句
cursor.execute(sql)
# 提交到数据库执行
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭数据库连接
db.close()
执行事务#!/usr/bin/python
# -*- coding: UTF-8 -*-
import MySQLdb
# 打开数据库连接
db = MySQLdb.connect("localhost","testuser","test123","TESTDB" )
# 使用cursor()方法获取操作游标
cursor = db.cursor()
# SQL 删除语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)
try:
# 执行SQL语句
cursor.execute(sql)
# 提交修改
db.commit()
except:
# 发生错误时回滚
db.rollback()
# 关闭连接
db.close()
对于支持事务的数据库, 在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。# SQL删除记录语句
sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20)
try:
# 执行SQL语句
cursor.execute(sql)
# 向数据库提交
db.commit()
except:
# 发生错误时回滚
db.rollback()
DB API中定义了一些数据库操作的错误及异常,下表列出了这些错误和异常:
异常 | 描述 |
---|---|
Warning | 当有严重警告时触发,例如插入数据是被截断等等。必须是 StandardError 的子类。 |
Error | 警告以外所有其他错误类。必须是 StandardError 的子类。 |
InterfaceError | 当有数据库接口模块本身的错误(而不是数据库的错误)发生时触发。 必须是Error的子类。 |
DatabaseError | 和数据库有关的错误发生时触发。 必须是Error的子类。 |
DataError | 当有数据处理时的错误发生时触发,例如:除零错误,数据超范围等等。 必须是DatabaseError的子类。 |
OperationalError | 指非用户控制的,而是操作数据库时发生的错误。例如:连接意外断开、 数据库名未找到、事务处理失败、内存分配错误等等操作数据库是发生的错误。 必须是DatabaseError的子类。 |
IntegrityError | 完整性相关的错误,例如外键检查失败等。必须是DatabaseError子类。 |
InternalError | 数据库的内部错误,例如游标(cursor)失效了、事务同步失败等等。 必须是DatabaseError子类。 |
ProgrammingError | 程序错误,例如数据表(table)没找到或已存在、SQL语句语法错误、 参数数量错误等等。必须是DatabaseError的子类。 |
NotSupportedError | 不支持错误,指使用了数据库不支持的函数或API等。例如在连接对象上 使用.rollback()函数,然而数据库并不支持事务或者事务已关闭。 必须是DatabaseError的子类。 |
建立数据库,进行一些简单操作
1.简单的创建一个’user‘表,并且插入一些数据。user表中只有两个字段:userid和username。代码如下:
import MySQLdb conn=MySQLdb.connect(host='127.0.0.1',port=3306,user='root',passwd='199331',db='test',charset='utf8') cur=conn.cursor() cur.execute(""" create table if not EXISTS user ( userid int(11) PRIMARY KEY , username VARCHAR(20) ) """) for i in range(1,10): cur.execute("insert into user(userid,username) values('%d','%s')" %(int(i),'name'+str(i))) conn.commit() cur.close() conn.close()
我们用Navicat打开数据库,查看一下结果,,可以看到成功创建表,并且插入了十个数据。
2.我们操作一下Cursor里面的一些方法。
execute()方法:执行SQL,将一个结果从数据库获取到客户端
fetch*()方法:移动rownumber,返回数据。
例如我们有如下代码:
sql='select * from user'
cursor.execute(sql)
print(cursor.rowcount)
rs=cursor.fetchone()
print(rs)
rs=cursor.fetchmany(3)
print(rs)
rs=cursor.fetchall()print(rs)
结果如下:
我们可以看出执行查询全部数据后,rowcount为10
执行fetchone()方法后返回一个数据,执行fetchmany(3)后返回3条数据,执行fetchall()后返回剩下的所有数据。
再有如下代码:
res=cursor.fetchall()
for row in res:
print('userid=%s,userna=%s' %row)
此时的执行结果为:
3.上面介绍的便是数据库中常说的Select操作,下面我们介绍数据的更新,即:insert、update、delete操作。值得注意的是在这部分操作时需要注意的是是否数据发生异常,如果数据没有发生异常,我们便可以直接使用commit()进行提交(注:如没有使用commit,则数据库不会发生任何变化)。但是如果出现了异常,那么久需要使用rollback()进行回滚。
3.1先来看一个没有异常,正常提交的例子:
sql_insert='insert into user(userid,username) values(10,"name10")'
sql_update='update user set username="name91" where userid=9'
sql_delete='delete from user where userid=3'
cursor.execute(sql_insert)
print(cursor.rowcount)
cursor.execute(sql_update)
print(cursor.rowcount)
cursor.execute(sql_delete)
print(cursor.rowcount)
conn.commit()
上面的操作即是:添加一条(10,’name10‘)的数据、将userid=9的username修改为’name91‘,删除userid=3的数据,执行上面代码后我们来用Navicat查看一下数据:
从结果可以看到代码执行正常。
3.2.再来看一个有异常的数据
sql_insert='insert into user(userid,username) values(10,"name10")'
sql_update='update user set username="name91" where userid=9'
# sql_delete='delete from user where userid=3'
# ##error
sql_delete='delete from user where useri=3'
try:
cursor.execute(sql_insert)
print(cursor.rowcount)
cursor.execute(sql_update)
print(cursor.rowcount)
cursor.execute(sql_delete)
print(cursor.rowcount)
except Exception as e:
print(e)
conn.rollback()
这里的insert和update操作一样,只不过把delete里面的userid字段错误的写成了useri,执行代码:
可以看到显示出异常,这时我们来看一下数据库数据:
数据没有任何改变。这就是rollback()的作用
因此,我们以后再写增删改查操作时,最好把操作放入一个try控制块中,来避免一些不必要的错误。
下面是一个银行转账的实例:
#-*-encoding:utf-8 -*-
import MySQLdb
conn=MySQLdb.connect(host='127.0.0.1',port=3306,user='root',passwd='199331',db='test',charset='utf8')
cur=conn.cursor()
##创建数据表
cur.execute("""
create table if not EXISTS account(
accid int(10) PRIMARY KEY ,
money int(10)
)
""")
###插入两行数据
cur.execute('insert into account(accid,money) VALUES (1,110)')
cur.execute('insert into account(accid,money) VALUES (2,10)')
conn.commit()
cur.close()
conn.close()
#-*- encoding:utf-8 -*-
import sys
import MySQLdb
class TransferMoney(object):
def __init__(self,conn):
self.conn=conn
def check_acct_available(self,accid):
cursor=self.conn.cursor()
try:
sql='select * from account where accid=%s' %accid
cursor.execute(sql)
print('check_acct_available'+sql)
rs=cursor.fetchall()
if len(rs)!=1:
raise Exception('账号%s 不存在' %accid)
finally:
cursor.close()
def has_enough_money(self,accid,money):
cursor=self.conn.cursor()
try:
sql='select * from account where accid=%s and money>%s' %(accid,money)
cursor.execute(sql)
print('check_money_available'+sql)
rs=cursor.fetchall()
if len(rs)!=1:
raise Exception('账号%s 没有足够钱' %accid)
finally:
cursor.close()
def reduce_money(self,accid,money):
cursor=self.conn.cursor()
try:
sql='update account set money=money-%s where accid=%s' %(money,accid)
cursor.execute(sql)
print('reduce money'+sql)
rs=cursor.fetchall()
if cursor.rowcount!=1:
raise Exception('账号%s 减款失败' %accid)
finally:
cursor.close()
def add_money(self,accid,money):
cursor=self.conn.cursor()
try:
sql='update account set money=money+%s where accid=%s' %(money,accid)
cursor.execute(sql)
print('reduce money'+sql)
rs=cursor.fetchall()
if cursor.rowcount!=1:
raise Exception('账号%s 加款失败' %accid)
finally:
cursor.close()
def transfer(self,source_accid,target_accid,money):
###检测两个账号是否可用
try:
self.check_acct_available(source_accid)
self.check_acct_available(target_accid)
####检测付款人是否有足够的钱
self.has_enough_money(source_accid,money)
self.reduce_money(source_accid,money)
self.add_money(target_accid,money)
self.conn.commit()
except Exception as e:
self.conn.rollback()
raise e
if __name__=='__main__':
source_accid=sys.argv[1]
target_accid=sys.argv[2]
money=sys.argv[3]
conn=MySQLdb.connect(host='127.0.0.1',port=3306,user='root',passwd='199331',db='test',charset='utf8')
tr_money=TransferMoney(conn)
try:
tr_money.transfer(source_accid,target_accid,money)
except Exception as e:
print('出现问题'+str(e))
finally:
conn.close()
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛