gyn

Win32下的Perl,无用的select,停滞的Tk,结束吧....

我对pysqlite的一些了解

大约是一年半或者是两年前的样子,在那段时间里,我似乎特别痴迷于各种数据库以及相关的技术。其间看了不少书,可能是平常工作接触的多是 sqlserver 的缘故,我本人对其反而不是特别的感冒,所以看的多是关于 postgresql oracle 的,尤其是前者。记得当时用的是一台 celeron1.7G 、内存 256MB 的方正电脑,安装这些软件让电脑变得非常的慢,终于在一次忍无可忍的僵死之后,我卸载了所有这些庞然大物。

之后台里引进了一台用于上下班记录的打卡机,为了方便统计迟到早退,我用 perl/tk 写了一个采集整理程序,后台用到了 sqlite ,这也是我和 sqlite 的初次邂逅。

至于对 python ,不好意思地说,我一直抱着骑墙的态度。如果 perl 可以解决的,我是断然不会用 python 的,这一切直到我对 poe 的幻想破灭为止。原先我是期待用 poe 来作为多线程的替代,可事实还是向着相反的方向发展。

sqlite 是一个嵌入式的数据库,也就是说没有独立的维护进程,所有的维护都来自于程序本身。麻雀虽小,五脏俱全, sqlite 实现了多数 sql-92 的标准,比如说 transaction trigger 和复杂的查询等。

有很多介绍的书籍,记得有一本 apress 出版的《 The difinitive guide to sqlite 》,有毛 500 面的样子,用来介绍一个嵌入式数据库,着实有点长了,当然对于初学者是有其存在的价值的。

pysqlite 则是一个 sqlite python 提供的 api 接口,它让一切对于 sqlite 的操作都变得异常简单。 userguide 并不长,但是基本上都说到点子上了,不过这里还是要对其提一下几个要点。事实上我个人认为,理解了这几点就完全足够了。

from pysqlite2 import dbapi2 as sqlite ”,   这就是一切的起源。

下面是一个涉及到我即将介绍的几点的示例程序,内容很简单,就是将一个 Point 对象存入 sqlite 建立的内存数据库中,然后原封不动地返回出来。

from pysqlite2 import dbapi2 as sqlite

class Point(object):

   def __init__(self, x, y):

      self.x, self.y = x, y

   def __conform__(self, protocol):

      if protocol is sqlite.PrepareProtocol:

          return "%d;%d" % (self.x, self.y)

 

def adapt_converter(point):

   return Point(*[int(x) for x in point.split(";")])

sqlite.register_converter('point', adapt_converter)

con=sqlite.connect(":memory:",detect_types= sqlite.PARSE_COLNAMES)

cur = con.cursor()

cur.execute('select ? as "a [point]"', (Point(2, 3), ))

print type(cur.fetchone()[0])

首先要做一些准备工作,因为 sqlite 不是什么 python 对象都能够接受的 , 为此需要一些必要的转换。这个例子里, sqlite 就像是一个汽车维修站。在站里,为了维修,汽车被拆成了个个零件,等出站时又被组装成了一辆汽车。

第一步是声明一个 Point 类。这个类除了初始化函数 __init__ 之外,还有一个两参量的函数 __conform__ sqlite 在检查存入数据库对象的时候会检查是否存在该函数,如果存在,则将该函数返回的值替代对象本身存入数据库。可以说这是一个转换器,将 python 对象转换为 sqlite 允许接纳对象,即 Null Integer Real Text Blob 其中之一。在这里,显然 sqlite 是无法接纳 Point 这个类所建立的 Point(2,3) 对象的,所以通过 __conform__ ,实际将存入内容为“ 2;3 ”的文本。

使用“ sqlite.register_adapter(Point, lambda p = point : “%d;%d” % p.x, p.y) ”,在 sqlite 中注册一个适配器也可以完成转换的功能,但是我个人认为这样比较麻烦,不如写在类里来得清楚。

在处理完了 Point 类之后,为了使文本“ 2;3 ”在从数据库取出时能转换为 Point 对象,还需要用“ sqlite.register_converter ”注册一个叫“ adapt_converter ”的转换器。

这样一条拆卸组装的流水线就完成了。

实际使用到的只有两样东西,一是数据库连接对象 con ,还有一个就是用来执行命令并返回结果(有必要的话)的游标对象 cur ,它是由 con 对象产生的。

为了使 sqlite 意识到它正在处理的表中的某一列是已注册需要转换的“ phone ”,我们需要在建立表的时候声明该列的属性,或者在查询的时候显示地表明该列的属性。对于前者,建立 con 对象是应将 detect_types 设置为 sqlite.PARSE_DELTYPES ;后者,则是设置为 sqlite.PARSE_COLNAMES 。这里,因为使用的是一个临时表,所以只能使用后者的设置办法。

事实上,“ select ? as …… ”这句包含了两个方面的内容,首先它将 Point(2, 3) 存入了临时表中,这涉及到了 Phone 对象到文本的转换。之后,再将文本数据从临时表中取出,又用到了文本到 Phone 的反转换。

下面是一种浅显而罗嗦的写法:

cur.execute("create table temp(t)")

cur.execute("insert into temp values (?)", (Point(2, 3),))

cur.execute('select ? as "a [point]" from temp')

最后,打印从 sqlite 中取出的对象类型,内容为“ <class '__main__.Point'> ”。

以上这些,可以总结为两点:有必要的话,做好转换;建立 con cur 。理解了这些,差不多就能用 pysqlite 了。当然如果要做工程、写程序还需要很多的其他知识,至少数据库设计这方面的内容是要看一下的。

posted on 2008-07-04 18:26 gyn_tadao 阅读(3012) 评论(2)  编辑 收藏 引用 所属分类: Python

评论

# re: 我对pysqlite的一些了解 2008-07-05 01:43 视频聊天

写的很好哦,努力啊  回复  更多评论   

# re: 我对pysqlite的一些了解 2015-10-03 14:38 JohnWu

Thanks for sharing! It's helpful to me.  回复  更多评论   

只有注册用户登录后才能发表评论。
<2015年10月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

导航

统计

常用链接

留言簿(14)

随笔分类(126)

随笔档案(108)

相册

搜索

最新评论

阅读排行榜

评论排行榜