Python 标准数据库接口为 Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。
Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:
你可以访问Python数据库接口及API查看详细的支持数据库列表。
不同的数据库你需要下载不同的DB API模块,例如你需要访问Oracle数据库和Mysql数据,你需要下载Oracle和MySQL数据库模块。
DB-API 是一个规范. 它定义了一系列必须的对象和数据库存取方式, 以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口 。
Python的DB-API,为大多数的数据库实现了接口,使用它连接各数据库后,就可以用相同的方式操作各数据库。
Python DB-API使用流程:
MySQLdb 是用于Python链接Mysql数据库的接口,它实现了 Python 数据库 API 规范 V2.0,基于 MySQL C API 上建立的。
为了用DB-API编写MySQL脚本,必须确保已经安装了MySQL。复制以下代码,并执行:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb
如果执行后的输出结果如下所示,意味着你没有安装 MySQLdb 模块:tError:Nomodule named MySQLdb
Traceback (most recent call last): File "test.py", line 3, in <module> import MySQLdb ImportError: No module named MySQLdb
1、下载 MySQL for Python
地址:http://sourceforge.net/projects/mysql-python/files/mysql-python/
我这里安装的是1.2.3版本
用安装python模块出现error: command 'gcc' failed with exit status 1 ,明明装了gcc的,怎么会不行呢,然后发觉是failed不是not found,这说明这个错误个gcc没多大关系,应该是缺少某些功能模块,然后谷歌了一下,先后安装了python-devel,libffi-devel后还是不行,最后发觉要安装openssl-devel才行
可如下命令行安装:
yum install gcc libffi-devel python-devel openssl-devel
再运行上面的安装命令
$ cd MySQL-python-1.2.3
$ python setup.py build
$ python setup.py install
把mysql_config的存放目录加入
如果不知道存放目录,可以用如下命令查看
[root@tanggao MySQL-python-1.2.3]# find / -name mysql_config /usr/bin/mysql_config我的存放目录是 /usr/bin/mysql_config
在最后一行加入mysql_config=/usr/bin/mysql_config
最后大功告成
测试一下:
bash: pthon: 未找到命令... [root@tanggao bin]# python Python 2.7.5 (default, Nov 20 2015, 02:00:19) [GCC 4.8.5 20150623 (Red Hat 4.8.5-4)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import MySQLdb >>>
先简单看看API,再看后面的案例
连接和游标
为了使用基础数据库系统,首先必须连接到它。这个时候需要使用具有恰当名称的connect函数,该函数有多个参数,而具体使用哪个参数取决于数据库。API定义了表13-3中的参数作为准则,推荐将这些参数作为关键字参数使用,并按表中给定的顺序传递它们。参数类型都应为字符串。
表13-3 connect函数的常用参数
参数名 描述 是否可选
dsn 数据源名称,给出该参数表示数据库依赖 否
user 用户名 是
password 用户密码 是
host 主机名 是
database 数据库名 是
connect函数返回连接对象。这个对象表示目前和数据库的会话。连接对象支持的方法如表13-4所示。
13-4 连接对象方法
close() 关闭连接之后,连接对象和它的游标均不可用
commit() 如果支持的话就提交挂事务,否则不做任何事
rollback() 回滚挂起的事务(可能不可用)
cursor() 返回连接的游标对象
rollback方法可能不可用,因为不是所有的数据库都支持事务(事务是一系列动作)。如果可用,那么它就可以“撤销”所有未提交的事务。
commit方法总是可用的,但是如果数据库不支持事务,它就没有任何作用。如果关闭了连接但还有未提交的事务,它们会隐式地回滚——但是只有在数据库支持回滚的时候才可以。所以如果不想完全依靠隐式回滚,就应该每次在关闭连接前进行提交。如果提交了,那么就用不着担心关闭连接的问题,它会在进行垃圾收集时自动关闭。当然如果希望更安全一些,就调用close方法,也不会敲很多次键盘。
cursor方法将我们引入另外一个主题:游标对象。通过游标执行SQL查询并检查结果。游标比连接支持更多的方法,而且可能在程序中更好用。表13-5给出了游标方法的概述,表13-6则是特性的概述。
表13-5 游标对象方法
callproc(name[, params]) 使用给定的名称和参数(可选)调用已命名的数据库程序
close() 关闭游标之后,游标不可用
execute(oper[, params]) 执行SQL操作,可能使用参数
executemany(oper, pseq) 对序列中的每个参数执行SQL操作
fetchone() 把查询的结果集中的下一行保存为序列,或者None
fetchmany([size]) 获取查询结果集中的多行,默认尺寸为arraysize
fetchall() 将所有(剩余)的行作为序列的序列
nextset() 跳至下一个可用的结果集(可选)
setinputsizes(sizes) 为参数预先定义内存区域
setoutputsize(size[, col]) 为获取的大数据值设定缓冲区尺寸
表13-6 游标对象特性
description 结果列描述的序列,只读
rowcount 结果中的行数,只读
arraysize fetchmany中返回的行数,默认为1
其中一些方法会在下面详细介绍,而有些(比如setinputsizes和setoutputsizes)则不会提到。更多细节请查阅PEP。
13.1.4 类型
数据库对插入到具有某种类型的列中的值有不同的要求,是为了能正确地与基础SQL数据库进行交互操作,DB API定义了用于特殊类型和值的构造函数以及常量(单例模式)。例如,如果想要在数据库中增加日期,它应该用相应的数据库连接模块的Date构造函数来建立。这样数据库连接模块就可以在幕后执行一些必要的转换操作。所有模块都要求实现表13-7中列出的构造函数和特殊值。一些模块可能不是完全按照要求去做,例如sqlite3模块(接下来会讨论)并不会输出表13-7中的特殊值(通过ROWIP输出STRING)。
表13-7 DB API构造函数和特殊值
Date(year, month, day) 创建保存日期值的对象
Time(hour, minute, second) 创建保存时间值的对象
Timestamp(y, mon, d, h, min, s) 创建保存时间戳值的对象
DateFromTicks(ticks) 创建保存自新纪元以来秒数的对象
TimeFromTicks(ticks) 创建保存来自秒数的时间值的对象
TimestampTicks(ticks) 创建保存来自秒数的时间戳的对象
Binay(string) 创建保存二进制字符串值的对象
STRING 描述基于字符串的列类型(比如CHAR)
BINARY 描述二进制列(比如LONG或RAW)
NUMBER 描述数字列
DATETIME 描述日期/时间列
ROWID 描述行ID列
连接数据库前,请先确认以下事项:
以下实例链接Mysql的TESTDB数据库:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db = MySQLdb.connect("localhost","root","tanggao","pythondb" ) # 使用cursor()方法获取操作游标 cursor = db.cursor() # 使用execute方法执行SQL语句 cursor.execute("SELECT VERSION()") # 使用 fetchone() 方法获取一条数据库。 data = cursor.fetchone() print "Database version : %s " % data # 关闭数据库连接 db.close()
执行以上脚本输出结果如下:
Database version : 5.6.32
如果数据库连接存在我们可以使用execute()方法来为数据库创建表,如下所示创建表EMPLOYEE:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db=MySQLdb.connect("localhost","root","tanggao","pythondb") # 使用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()
以下实例使用执行 SQL INSERT 语句向表 EMPLOYEE 插入记录:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db=MySQLdb.connect("localhost","root","tanggao","pythondb") # 使用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","root","tanggao","pythondb") # 使用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()
以下代码使用变量向SQL语句中传递参数:
.................................. user_id = "test123" password = "password" con.execute('insert into Login values("%s", "%s")' % \ (user_id, password)) ..................................
Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。
查询EMPLOYEE表中salary(工资)字段大于1000的所有数据:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db=MySQLdb.connect("localhost","root","tanggao","pythondb") # 使用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
更新操作用于更新数据表的的数据,以下实例将 TESTDB表中的 SEX 字段全部修改为 'M',AGE 字段递增1:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db=MySQLdb.connect("localhost","root","tanggao","pythondb") # 使用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()
删除操作用于删除数据表中的数据,以下实例演示了删除数据表 EMPLOYEE 中 AGE 大于 20 的所有数据:
#!/usr/bin/python # -*- coding: UTF-8 -*- import MySQLdb # 打开数据库连接 db=MySQLdb.connect("localhost","root","tanggao","pythondb") # 使用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()
事务机制可以确保数据一致性。
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
Python DB API 2.0 的事务提供了两个方法 commit 或 rollback。
# SQL删除记录语句 sql = "DELETE FROM EMPLOYEE WHERE AGE > '%d'" % (20) try: # 执行SQL语句 cursor.execute(sql) # 向数据库提交 db.commit() except: # 发生错误时回滚 db.rollback()
对于支持事务的数据库, 在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。
commit()方法游标的所有更新操作,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的子类。 |