13.13 sqlite3 -- DB-API 2.0 interface for SQLite databases
在2.5版本中新增。
SQLite是一个提供轻量级的基于磁盘的数据库的C语言库,它不需要一个独立的服务进程,并且允许你使用一种非标准的SQL查询语言来访问数据库。其他程序也可以使用SQLite来管理内部数据存储。你也可以使用SQLite来构建应用程序原型,然后把代码迁移到一个更大的数据库,比如PostgreSQL或者Oracle。
pysqlite是Gerhard Haring写的,提供一个与PEP 249描述的DB-API 2.0规格说明书兼容的SQL接口。
要使用这个模块,你必须现创建一个代表数据库的连接对象(Connection object)。如下的数据将被存储在/tmp/example文件中:
conn = sqlite2.connect('/tmp/example')
你还可以提供一个特殊的名称":memory:"在内存中来创建一个数据库。
一旦你建立了一个连接(Connection),你就可以创建一个游标对象(Cursor object),并且调用它的execute()方法来执行SQL命令:
c = conn.cursor()
#Creat table
c.execute('''creat table stocks
(data text,trans text,symbol text,
qty real,price real)''')
#Insert a row of data
c.execute('''insert into stocks
values('
2006-01-05
','BUY','RHAT',100,35.14)''')
通常你的SQL操作会用到你的Python程序中的变量的值。你不应该使用Python的字符串操作符来集合你的查询,因为这样是不安全的;它使你的程序容易首道SQL注入攻击。
替代方法是使用DB-API的参数交换。在你需要使用一个变量的时候,使用"?"作为一个占位符,然后提供一个包含变量的元组作为油表对象的execute()方法的第二个参数。(其他的数据库模块可能使用不同的占位符,比如"%s"或者":1"。)例如:
#Never do this -- insecure!
symbol = 'IBM'
c.execute('''... where symbol = '%s' % symbol)
#Do this instead
t = (symbol,)
c.execute('select * from stocks where symbol=?',t)
#Larger example
for t in (('
2006-03-28
','IBM',1000,45.00),
('
2006-04-05
','MSOFT',72.00),
('
2006-04-06
','SELL',500,53.00),
):
c.execute('insert into stocks values (?,?,?)',t)
为了在执行一个select语句后返回数据,你既可以把游标作为一个迭代器来对待,调用游标对象的fetchone()方法来返回一个单一的匹配行,也可以调用fetchall()方法得到一个所有匹配行的列表。
下面这个例子使用了迭代器的方式:
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
... print row
...
(u'
2006-01-05
',u'BUY',u'RHAT',35.140000000000001)
(u'
2006-03-28
',u'IBM',45.0)
(u'
2006-04-06
',u'SELL',53.0)
(u'
2006-04-05
',u'MSOFT',72.0)
>>>
See Also:
http://www.pysqlite.org
pysqlite的网站。
http://www.sqlite.org
SQLite的网站;相关文档描述了语法以及对其支持的可爱的SQL的可用的数据类型。
PEP 249,Database API Specification 2.0
Marc-André Lemburg写的PEP。
13.13.1
模块函数和常量
PARSE_DECLTYPES
这个常量是用来作为connect函数的参数detect_types的值使用的。
设置它使sqlite3模块解析返回的每一列的声明类型。他会解析出声明类型中的第一个词,i. e. 对于'integer primary key',将会解析出'integer'。然后对于这一列,他会在转换字典中查找并且使用对这种类型注册的转换函数。注意:转换器的名称是大小写敏感的!
PARSE_COLNAMES
这个常量是用来作为connect函数的参数detect_types的值使用的。
设置它使SQLite接口解析返回的每一列的列名字。他会在其中查找一个这样书写的字符串[mytype],然后将‘mytype’作为这一列的类型。他将尝试在转换字典中查找‘mytype’的入口,然后使用在字典中找到的转换函数来返回值。在cursor.description中找到的名字只是这个列的第一个字,i. e. 如果你在SQL中使用这样的语句:'as "x [datetime]"',那么将会解析出直到列名字中第一个空格出现时的任何字符——这个列的名字只是一个简单的'x'。
connect(database[,timeout,isolation_level,detect_types,factory])
打开一个到SQLite数据库文件database的连接。你可以使用':memory:'来打开一个驻留在内存中而不是在磁盘上的数据库连接。
当一个数据库被多重连接时(when a database is accessed by multiple connections),并且有一个进程更改了数据库,这个SQLite数据库将会被锁住直到交易被执行。timeout参数指定这个连接在抛出一个异常之前等待的时间。默认的timeout参数是5.0(5秒钟)。
对于isolation_level参数,请查看在
13.13.2
中描述的连接对象(Connection objects)的isolation_level属性。
SQLite本身只支持TEXT,INTEGER,FLOAT,BLOB和NULL类型。如果你希望使用其他类型,你需要添加自己的支持。detect_types参数,以及使用定制的利用模块级的register_converter函数注册的converters,可以让你很容易实现它。
detect_types默认为0(i. e. off,没有类型检测),你可以设置其为PARSE_DECLTYPES和PARSE_COLNAMES的任意组合来将类型检测打开。
sqlite3默认模块使用其Connection类来实现connection调用。然而,你可以编写Connection类的一个子类,然后将你的类提供给factory参数来使用你自己的类建立连接。
详细信息请参阅本手册的
13.13.4
章节。
register_converter(typename,callable)
注册一个转换器(callable)来将数据库中的字节串转换为一个Python类型。对于数据库中的所有typename类型的数据,这个转换器都将被调用。Confer the parameter detect_types of the connect function for how the type detection works.注意:typename和你的查询中的类型名字的大小写必须匹配。
register_adapter(type,callable)
注册一个转换器来将Python中的type类型转换为SQLite支持的一种类型。转换器只callable接受一个单一的Python值作为参数,也必须返回这些类型中的一个值:int,long,float,str(UTF-8 encoded),unicode代码或字节流。
complete_statement(sql)
返回True如果字符串sql是一个或多个用分号结束的SQL语句。它不能识别出错误,如果SQL语句在语法上是正确的,仅仅是在语义上不完整,但是语句是以分号结束的。
者可以用来构建一个SQLite的解释器,就如下面的例子一样:
#A minimal SQLite shell for experiments
import sqlite3
con = sqlite3.connect(":memory:")
con.isolation_level = None
cur = con.cursor()
buffer = ""
print "Enter your SQL commands to execute in sqlite3."
print "Enter a blank line to exit."
while True:
line = raw_input()
if line == "":
break
buffer += line
if sqlite3.complete_statement(buffer):
try:
buffer = buffer.strip()
cur.execute(buffer)
if buffer.lstrip().upper().startswith("SELECT"):
print cur.fetchall()
except sqlite3.Error,e:
print "An error occurred:",e.args[0]
buffer = ""
con.close()
enable_callback_tracebacks(flag)
默认情况下,在用户定义的functions,aggregates,converters,authorizer等中你不会得到任何跟踪信息。如果你想要调试它们,你就可以用True作为flag参数的值来调用这个函数。之后,你就可以在sys.stderr中得到从回调中返回的跟踪信息。使用False来再次关闭这个功能。
13.13.2
连接对象(Connection Objects)
一个连接实例具有以下属性和方法:
isolation_level
得到或设置当前的隔离级别(isolation level)。设置为None使用自动模式,或"DEFERRED","IMMEDIATE"或"EXLUSIVE"。更具体的说明请参考
13.13.5
章中的"Controlling Transactions"。
cursor([cursorClass])
cursor方法接受一个单一的cursorClass参数。如果这个参数被提供,则必须是一个扩展了sqlite3.Cursor类的定制cursor类。
execute(sql,[parameters])
这是一个非标准的,通过调用cursor方法创建一个中间cursor对象的快捷方式,然后使用给出的参数调用cursor的execute方法。
executemany(sql,[parameters])
这是一个非标准的,通过调用cursor方法创建一个中间cursor对象的快捷方式,然后使用给出的参数调用cursor的executemany方法。
executescript(sql_script)
这是一个非标准的,通过调用cursor方法创建一个中间cursor对象的快捷方式,然后使用给出的参数调用cursor的executescript方法。
creat_function(name,num_params,func)
创建一个用户定义的函数,创建以后你可以在SQL语句中通过name名字使用,num_params是这个函数接受的参数的数量,func是一个作为SQL函数的Python调用器。
这个函数返回SQLite支持的任意类型:unicode,str,int,buffer和None。
Example:
import sqlite3
import md5
def md5sum(t):
return md5.md5(t).hexdigest()
con = sqlite3.connect(":memory:")
con.creat_function("md5",1,md5sum)
cur = con.cursor()
cur.execute("select mdt(?)",("foo",))
print cur.getchone()[0]
creat_aggregate(name,aggregate_class)
创建一个用户定义的聚合函数。
一个聚合类必须提供一个step方法,它接受参数的数量num_params,和一个finalize方法,它返回最终的聚合结果。
finalize方法可以返回SQLite支持的任何类型:unicode,buffer和None。
Example:
import sqlite3
class MySum:
def __init__(self):
self.count = 0
def step(self,value):
self.count += value
def finalize(self):
return self.count
con = sqlite3.connect(":memory:")
con.creat_aggregate("mysum",MySum)
cur = con.cursor()
cur.execute("create table test(i)")
cru.execute("insert into test(i) values (1)")
cru.execute("insert into test(i) values (2)")
cur.execute("select mysum(i) from test")
print cur.fetchone()[0]
creat_collation(name,callable)
使用指定的name和callable创建一个校对。调用器会被传入两个字符串参数。它应该返回-1,如果第一个排序比第二个低,返回0,如果两个排序一致,返回1,如果第一个排序比第二个高。需要指出的是,这个操作控制着排序(ORDER BY in SQL),因此,你的比较不会影响其他SQL操作。
注意:调用器将会按照Python的字节码来接受参数,这些参数通常的编码是UTF-8。
下面的例子显示了一个定制的对"the wrong way"进行排序的校对:
import sqlite3
def collate_reverse(string1,string2):
return -cmp(string1,string2)
con = sqlite3.connect(":memory:")
con.create_collation("reverse",collate_reverse)
cur = con.cursor()
cur.execute("creat table test(x)")
cur.executemany("insert into test(x) values (?)",[("a",),("b",)])
cur.execute("select x from test order by x collate reverse")
for row in cur:
print row
con.close()
如果要删除一个校对,用None作为调用器来调用create_collation:
con.create_collation("reverse",None)
interrupt()
你可以从另一个线程中调用这个方法来中断一个连接上可能进行的任何查询操作。查询操作将会中断,查询的调用者将会得到一个异常。
set_authorizer(authorizer_callback)
这个动作注册一个调用器。在每一次尝试访问数据库中的一个表中的一列时,这个调用器都将会被调用。调用器应该返回SQLITE_OK,如果访问被允许,返回SQLITE_DENY,如果整个SQL语句因为错误而应该被中断,返回SQLITE_IGNORE,如果这一列应该作为NULL值来对待。这些实例在sqlite3模块中可用。
调用器的第一个参数表明什么类型的操作要进行审定。第二个参数和第三个参数根据第一个参数,会使参数或者None。如果可用的话,第四个参数是数据库的名字("main","temp"等等)。第五个参数是对试图进行的访问负责的最内的(inner-most)触发器的名字或者视图,或者为None如果这个访问直接来自于SQL代码。
关于第一个参数的可能的取值,以及依赖于第一个参数的第二个和第三个参数的含义,请参阅SQLite的文档。所有的必须的常量在sqlite3模块中都是可用的。
row_factory
你可以将这个属性改变为一个调用器的名字,这个调用器接受一个游标和一行的元组,返回计算后的行。这样,你可以实现返回结果的更高级的方法,比如,返回一个任然可以通过名字访问列的对象。
Example:
import sqlite3
def dict_factory(cursor,row):
d = {}
for idx,col in enumerate(cursor.description):
d[col[0]] = row[idx]
return d
con = sqlite3.connect(":memory:")
con.row_factory = dict_factory
cur = con.cursor()
cur.execute("select 1 as a")
print cur.fetchone()["a"]
如果返回一个元组不能满足需要,而你想要对列的基于名字的访问,那么你可以考虑将row_factory设置为高度优化的sqlite3.Row类型。Row既提供基于索引的,也提供基于名字的对列的访问,却几乎不需要消耗额外的内存。它可能会比你自己定制的基于字典的访问甚至基于db_row的解决方法还要好。
text_factory
使用这个属性你可以控制对于TEXT数据类型返回什么样的对象。默认情况下,这个属性被设置为unicode,对于TEXT,sqlite3模块会返回Unicode对象。如果你希望返回字节串(bytestrings)来替代,你可以设置其为str。
你也可以将其设置为任何接受一个单一字节串参数并且返回最终对象的调用器。
参考下面的解释实例代码:
import sqlite3
con = sqlite3.connect(":memory:")
cur = con.cursor()
#Create the table
con.execute("create table person(lastname,firstname):)
AUSTRIA
= u"/xd6sterreich"
# by default,rows are returned as Unicode
cur.execute("select ?",(
AUSTRIA
,))
row = cur.fetchone()
assert type(row[0]) == str
# the bytestrings will be encoded in UTF-8,unless you stored garbage in the
# database ...
assert row[0] == AUSTRIA.encode("uft-8")
# we can also implement a custom text_factory ...
# here we implement one that will ignore Unicode characters that cannot be
# decoded form UTF-8
con.text_factory = lambda x: unicode(x,"utf-8","ignore")
cur.execute("select ?",("this is latin1 and would normally create errors" + u"/xe4/xf6/xfc".encode("latin1"),))
row = cur.fetchone()
assert type(row[0]) == unicode
# pysqlite offers a builtin optimized text_factory that will return bytestring
# objects,if the data is in ASCII only,and otherwise return unicode objects
con.text_factory = sqlite3.OptimizedUnicode
cur.execute("select ?",))
row = cur.fetchone()
assert type(row[0]) == unicode
cur.execute("select ?",("
germany
",))
row = cur.fetchone()
assert type(row[0]) == str
total_changes
返回从数据库连接开始后的所有被修改,插入或删除的行数。
13.13.3
游标对象(Cursor Objects)
一个游标实例拥有以下属性和方法:
execute(sql,[parameters])
执行一条SQL语句。这条SQL语句可能是参数化了(parametrized)的(i. e. 用占位符替代了SQL文字)。sqlite3模块支持两种类型的占位符:问号(问好风格)和命名占位符(命名风格)。
这个例子展示了怎样使用问号风格的参数:
import sqlite3
con = sqlite3.connect("mydb")
cur = con.cursor()
who = "Yeltsin"
age = 72
cur.execute("select name_last,age from people where name_last=? and age=?",(who,age))
print cur.fetchone()
下面的例子展示了如何使用命名风格:
import sqlite3
con = sqlite3.connect("mydb")
cur = con.cursor()
who = "Yeltsin"
age = 72
cur.execute("select name_last,age from people where name_last=:who and age=:age",{"who": who,"age": age})
print cur.fetchone()
execute()方法执行一条单一SQL语句。如果你试图用其执行多余一条的语句,将会抛出一个警告(Warning)。你可以是用executescript()来再一次调用中执行多条SQL语句。
executemany(sql,seq_of_parameters)
执行一条SQL语句利用所有参数序列,或者从参数中得到的遍历图(mappings)。sqlite3模块也允许使用迭代器生成参数来替代序列。
import sqlite3
class IterChars:
def __init__(self):
self.count = ord('a')
def __iter__(self):
return self
def next(self):
if self.count > ord('z'):
raise StopIteration
self.count += 1
return (chr(self.count - 1),) # this is a 1-tuple
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("create table characters(c)")
theIter = IterChars()
cur.executemany("insert into characters(c) values (?)",theIter)
cur.execute("select c from characters")
print cur.fetchall()
下面是一个使用生成器的小例子:
import sqlite3
def char_generator():
import string
for c in string.letters[:26]:
yield (c,)
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("create table charaters(c)")
cur.executemany("insert into characters(c) values (?)",char_generator())
cur.execute("select c from characters")
print cur.fetchall()
executescript(sql_script)
这是一个非标准的一次执行多条SQL语句的简便方法。它首先提交一个COMMIT语句,然后将接收到的SQL语句作为参数。
sql_script可以是一个字节串,也可以是一个Unicode字符串。
Example:
import sqlite3
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.executescript("""
create table person(
firstname,
lastname,
age
);
create table book(
title,
author,
published
);
insert into book(title,author,published)
values (
'Dirk Gently''s Holistic Detective Agency',
'Douglas Adams',
1987
);
""")
rowcount
虽然sqlite3模块的游标类提供这一个属性,但是数据库引擎本身对"rows affected"/"rows selected"的定义的支持要更快一些。
对于select语句,rowcount总是None,以为在所有行都被取出之前,我们无从得知一个查询所产生的行数。
对于delete语句,如果你使用DELETE FROM而没有任何条件的话,SQLite将rowcount作为0报告。
根据Python DB API Spec的要求,这个rowcount属性“是-1,如果在这个游标上还没有executeXX()被执行过,或者其最后一册操作的rowcount对于接口不可知。”
13.13.4
SQLite and Python types
13.13.4
.1 Introduction
SQLite本身支持以下类型:NULL,REAL,TEXT,BLOB.
从而,如下的Python类型可以直接存入SQLite,而不会出现任何问题:
|