python Database API Specification v2.0

来源:互联网 发布:经济学的书 知乎 编辑:程序博客网 时间:2024/04/28 12:16

1.模块接口
  a.方法:
    connect(parameters...)
 创建一个数据库连接,返回Connection对象
 可能的参数有:
        dsn         数据源名称
        user        用户名
        password    密码
        host        主机名
        database    数据库名
  b.常量
    apilevel
 字符串常量,用于指明支持的DB API 版本.目前仅仅允许 "1.0" 和 "2.0",如果没有指定,默认是"1.0"

   threadsafety
 整数常量,用于指明支持的线程安全(thread safety)级别,可能的值有:
     0      线程不能共享模块
        1     线程除了连接以外可以共享模块
        2     线程可以共享连接和模块
        3     线程可以共享连接,游标和模块
        共享意味着两个线程可以使用资源,而不需要使用互斥锁锁住资源

    paramstyle
 字符串常量,用于指明支持的sql参数格式,可能的值有:
     'qmark'         支持'...WHERE name=?'的'?'占位格式
        'numeric'       支持'...WHERE name=:1'的位置参数
        'named'         支持'...WHERE name=:name'的命名参数
        'format'        支持'...WHERE name=%s'的C语言printf风格
        'pyformat'      支持'...WHERE name=%(name)s'的python扩展格式化格式

  c.异常
    StandardError
    |
    |-Warning
 |  当插入数据时截断等操作发生时,引发Warning,Warning必须是Python StandardError
 |  (定义在exceptions模块中)的子类
 |-Error
    | 其他异常的超类,可以使用Error捕获所有数据库操作异常.Warning不认为是异常.Error必须是
    | Python StandardError的子类
    |
    |-InterfaceError
    | 代表Python DB API 实现的接口错误而并非数据库本身的错误,Error的子类
    |
    |-DatabaseError
        | 代表数据库相关的错误,Error的子类
        |
        |-DataError
     |     数据处理的错误,比如除0错误,整数超过精度等,DatabaseError的子类
     |
     |-OperationalError
     |  数据库操作错误,比如数据源未找到,事务无法处理,内存分配错误等等,DatabaseError的子类
     |
     |-IntegrityError
     |  数据完整性不一致错误,比如外键检查错误等.DatabaseError的子类
     |
     |-InternalError
     |  数据库内部错误,比如游标无效(游标关闭后继续调用),事务不同步等.DatabaseError的子类
     |
     |-ProgrammingError
     |  编程错误,比如表不存在,SQL语法错误等.DatabaseError的子类
     |
     |-NotSupportedError
     数据库不支持DB API中某些方法错误,比如,在不支持事务的数据库上调用rollback操作.
     DatabaseError的子类

2.Connection对象
  a.方法
    close()
 关闭连接,调用close()以后Connection对象将不再可用,此后在此Connection对象以及该连接创建的Cursor对象上调用方法
    将引发异常.注意:在没有提交事务的情况下关闭连接将隐式的回滚事务.

    commit()
 提交当前事务.如果数据库支持自动提交的特性,初始化连接对象的时候这个特性是被关闭的.在不支持事务的数据库上此方法无效.

 rollback()
 回滚当前事务.在不支持事务的数据库上引发异常

 cursor()
 返回该Connection对象创建的Cursor对象

3.Cursor对象
  Cursor对象代表了数据库的游标,用于管理数据库操作的上下文环境.同一个Connection创建的Cursor对象并不隔离,也就是说其中
  一个Cursor对象修改的数据可以被立刻反映给另一个Cursor对象.而不同Connection创建的Cursor对象可以也可以不隔离,这要
  取决于数据库支持隔离的程度.
  a.属性
    description
 由7个元素组成的序列,格式为
 (name, type_code,display_size, internal_size, precision, scale,null_ok).
 前两个元素(name和type_code)是必须的,后五个可选并且当不能提供有意义的值时必须设置成None
 description属性当没有返回记录或者Cursor对象没有调用executeXXX()方法时可能返回None
 type_code可以被下面介绍的Type对象解释

 rowcount
 最后一个查询(select)返回的记录数或者最后一次操作(insert,update)影响的记录数
 如果没有执行executeXXX,这个属性返回-1(以后的DB API可能会改成返回None)

 arraysize
 这个设置指定了fetchmany方法一次取多少行记录,默认值是1


  b.方法
 callproc(procname[,parameters])
 调用存储过程,由于并非所有数据库支持存储过程,所以这个方法是可选的
 参数procname是存储过程名,参数parameters序列必须符合存储过程需要的参数.调用的结果是输入的parameters序列的修改后
 的一个拷贝.存储过程输入参数不会改变,输出参数和输入/输出参数可能会替换成新的值
 存储过程也可以返回一个结果集,这可以通过fetchXXX方法获取

 close()
 关闭游标.调用close()以后Cursor对象将不再可用,此后在此Cursor对象上调用方法将引发异常

 execute(operation[,parameters])
 执行数据库操作(查询或者命令).parameters可以以序列或者映射的形式绑定到operation.
 Cursor对象可以保留operation的引用,这样当相同的operation再次执行的时候,Cursor对象能够优化操作.这是在执行相同
 operation但提供不同的参数的情况下最有效的优化算法.

 executemany(operation[,seq_of_parameters])
 使用seq_of_parameters所有的元素(序列或者映射)执行数据库操作(查询或者命令)
 一些DB API实现可能是通过在方法中多次调用execute来完成这个操作的

 fetchone()
 获得查询结果集的下一行数据,返回一个序列,这个序列中包含了数据表每一列的值,当没有下一行数据时返回None
 如果之前的executeXXX方法没有返回结果集或者根本没有调用executeXXX的时候,这个方法将抛出异常

 fetchmany([size = cursor.arraysize])
 返回查询结果集中指定长度的子集,通常是一个包含序列元素的序列(如:由tuple组成的list).当没有子集的时候返回空序列
 子集的长度是由size参数指定的,没有指定的情况下使用Cursor对象的arraysize属性,如果数据表中没有指定长度的数据行,
 那么将返回最大的可能值.
 如果之前的executeXXX方法没有返回结果集或者根本没有调用executeXXX的时候,这个方法将抛出异常

 fetchall()
 返回查询结果集中所有剩余行的序列,通常是一个包含序列元素的序列(如:由tuple组成的list).
 注意:Cursor对象的arraysize属性将影响这个方法的性能.
 如果之前的executeXXX方法没有返回结果集或者根本没有调用executeXXX的时候,这个方法将抛出异常

 nextset()
 使Cursor对象跳转到下一个结果集,由于并非所有数据库都支持多重结果集,所以这个方法是可选的
 如果没有更多的结果集,这个方法返回None.否则将返回true,在以后调用fetchXXX方法后将会得到数据
 如果之前的executeXXX方法没有返回结果集或者根本没有调用executeXXX的时候,这个方法将抛出异常

4.Type对象和构造器
 许多数据库在将参数绑定到指定的操作上需要有特殊的格式.比如,网DATA类型的列上插入数据的时候就需要有不同的格式.现在
 的问题是:由于传递到executeXXX方法上的参数是没有类型的(仅仅是string),那么数据库如何知道您将要插入的是日期格式呢?
 为了解决这个问题,DB API实现模块必须提供下面的构造器,用于创建指定类型的对象.当把这些对象传递给Cursor后,此时就可以
 准确的探测类型并正确的绑定了.

 构造器

 Date(year,month,day)       日期
 Time(hour,minute,second)       时间
 Timestamp(year,month,day,hour,minute,second)  日期和时间
 DateFromTicks(ticks)       从新纪元以来的秒数计算出来的日期
    TimeFromTicks(ticks)       从新纪元以来的秒数计算出来的时间
    TimestampFromTicks(ticks)      从新纪元以来的秒数计算出来的日期和时间
    Binary(string)         给定字符串的二进制值

 Cursor对象的descriptor方法返回的序列中,type_code必须是下面的某个类型,而Type对象可以和多个type_code相等.

    STRING           描述数据库的字符列,如CHAR
    BINARY           描述数据库的二进制列,如LONG, RAW, BLOBs
    NUMBER           描述数据库的数字列
    DATETIME          描述数据库的日期/时间列
    ROWID           描述数据库的"Row ID"列

    SQL NULL 值用python的None表示


5.使用MySQLdb(python DB API实现)连接mysql数据库的示例

 #数据库名misc
 #表脚本
 #CREATE TABLE user (
 #  id int(11) NOT NULL auto_increment,
 #  name varchar(20) NOT NULL default '',
 #  email varchar(255) default NULL,
 #  mobile varchar(40) default NULL,
 #  createtime timestamp(14) NOT NULL,
 #  PRIMARY KEY  (id)
 #  ) TYPE=InnoDB;


 import MySQLdb as mysql
 import time

 class User(object):
     attributes = ['id','name','email','mobile']  #用户对象允许的属性
     def __init__(self,dbrow=()):
      """
      初始化用户

      dbrow - 数据表的一行数据
      """

      #从一行数据表构造User对象
         if dbrow:
             for attr,value in zip(User.attributes,dbrow):
                 self.__dict__[attr] = value

     def __setitem__(self,key,value):
         if not key in User.attributes:
             raise AttributeError,"%s not acceptable" %key
         self.__dict__[key] = value

     def __getitem__(self,key):
         if not key in self.__dict__:
             raise AttributeError,"%s not found" %key
         return self.__dict__[key]

     def __str__(self):
         return "%(name)s,%(email)s,%(mobile)s" %self.__dict__

 class UserService(object):
     def __init__(self,connection):
         self.connection = connection

     def createUser(self,user):
      """
      创建新用户

      user - User类实例
      """
         insertsql = "insert into user (name,email,mobile,createtime) values (%s,%s,%s,%s)"
         cursor = self.connection.cursor()
         cursor.execute(insertsql,(user.name,user.email,user.mobile,mysql.TimestampFromTicks(time.time())))
         self.connection.commit()
         cursor.close()

     def findAllUsers(self):
      """
      查询所有用户
      """
         selectsql = "select * from user"
         cursor = self.connection.cursor()
         cursor.execute(selectsql)
         allusers = []    #方法返回list,其中的元素为每个user对象
         for row in cursor.fetchall():
             allusers.append(User(row))
         cursor.close()
         return allusers

 if __name__ == "__main__":

     connection = mysql.connect(db="misc")
     print connection
     userService = UserService(connection)
     user = User()
     user['name'] = '中文用户名'
     user['email'] = 'snowway.xue@gmail.com'
     user['mobile'] = '13916766714'
     userService.createUser(user)

     for user in userService.findAllUsers():
         print user
     connection.close()

原创粉丝点击