做自(zì)由與創造的先行者

數據持久性 | Data Persistence sqlite3

Python開(kāi)發手冊

2.5版本中的新功能(néng)。

SQLite是一個C庫,它提供了(le)一個輕量級的基于磁盤的數據庫,它不需要單獨的服務器進程,并允許使用(yòng)SQL查詢語言的非标準變體訪問數據庫。一些(xiē)應用(yòng)程序可以使用(yòng)SQLite進行内部數據存儲。也(yě)可以使用(yòng)SQLite對(duì)應用(yòng)程序進行原型設計(jì),然後将代碼移植到(dào)更大(dà)的數據庫,如PostgreSQL或Oracle。

sqlite3模塊由GerhardHäring編寫。它提供了(le)一個符合PEP 249描述的DB-API 2.0規範的SQL接口。

要使用(yòng)該模塊,您必須首先創建一個Connection代表數據庫的對(duì)象。這(zhè)裏的數據将被存儲在example.db文(wén)件中:

import sqlite3

conn = sqlite3.connect('example.db')

複制

您還可以提供特殊名稱:memory:以在RAM中創建數據庫。

一旦你(nǐ)有了(le)Connection,你(nǐ)可以創建一個Cursor對(duì)象并調用(yòng)它的execute()方法來(lái)執行SQL命令:

c = conn.cursor()

# Create table

c.execute('''CREATE TABLE stocks

(date 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)")

# Save (commit) the changes

conn.commit()

# We can also close the connection if we are done with it.

# Just be sure any changes have been committed or they will be lost.

conn.close()

複制

您保存的數據是持久性數據,可在以後的會(huì)話(huà)中使用(yòng):

import sqlite3

conn = sqlite3.connect('example.db')

c = conn.cursor()

複制

通常你(nǐ)的SQL操作(zuò)需要使用(yòng)Python變量的值。你(nǐ)不應該使用(yòng)Python的字符串操作(zuò)來(lái)組裝你(nǐ)的查詢,因爲這(zhè)樣做是不安全的; 它會(huì)使您的程序容易受到(dào)SQL注入攻擊(有關可能(néng)出錯的幽默示例,請(qǐng)參閱https://xkcd.com/327/)。

而是使用(yòng)DB-API的參數替換。将?作(zuò)爲占位符,無論你(nǐ)想使用(yòng)的值,然後提供值的元組作(zuò)爲第二個參數光标的execute()方法。(其他(tā)數據庫模塊可能(néng)使用(yòng)不同的占位符,例如%s或:1)。例如:

# Never do this -- insecure!

symbol = 'RHAT'

c.execute("SELECT * FROM stocks WHERE symbol = '%s'" % symbol)

# Do this instead

t = ('RHAT',)

c.execute('SELECT * FROM stocks WHERE symbol=?', t)

print c.fetchone()

# Larger example that inserts many records at a time

purchases = [('2006-03-28', 'BUY', 'IBM', 1000, 45.00),

('2006-04-05', 'BUY', 'MSFT', 1000, 72.00),

('2006-04-06', 'SELL', 'IBM', 500, 53.00),

]

c.executemany('INSERT INTO stocks VALUES (?,?,?,?,?)', purchases)

複制

要在執行SELECT語句後檢索數據,可以将遊标作(zuò)爲叠代器,調用(yòng)遊标的fetchone()方法來(lái)檢索單個匹配的行,或者調用(yòng)fetchall()獲取匹配行的列表。

這(zhè)個例子使用(yòng)叠代器形式:

>>> for row in c.execute('SELECT * FROM stocks ORDER BY price'):

print row

(u'2006-01-05', u'BUY', u'RHAT', 100, 35.14)

(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)

(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)

(u'2006-04-05', u'BUY', u'MSFT', 1000, 72.0)

複制

1.模塊功能(néng)和(hé)常量

sqlite3.version

此模塊的版本号,作(zuò)爲字符串。這(zhè)不是SQLite庫的版本。

sqlite3.version_info

該模塊的版本号,作(zuò)爲整數的元組。這(zhè)不是SQLite庫的版本。

sqlite3.sqlite_version

運行時(shí)SQLite庫的版本号,作(zuò)爲字符串。

sqlite3.sqlite_version_info

運行時(shí)SQLite庫的版本号,作(zuò)爲整數的元組。

sqlite3.PARSE_DECLTYPES

該常數用(yòng)于與函數的detect_types參數一起使用(yòng)connect()。

設置它會(huì)使sqlite3模塊解析它返回的每一列的聲明(míng)類型。它會(huì)解析出聲明(míng)類型的第一個單詞,即對(duì)于“整數主鍵”,它将解析出“整數”,或者對(duì)于“編号(10)”,它将解析出“編号”。然後,對(duì)于該列,它将查看(kàn)轉換器字典并使用(yòng)在那裏注冊的轉換器函數。

sqlite3.PARSE_COLNAMES

該常數用(yòng)于與函數的detect_types參數一起使用(yòng)connect()。

設置這(zhè)使得SQLite接口解析它返回的每一列的列名。它會(huì)在那裏尋找一個形成mytype的字符串,然後決定'mytype'是該列的類型。它會(huì)嘗試在轉換器字典中找到(dào)'mytype'條目,然後使用(yòng)在那裏找到(dào)的轉換器函數返回值。找到(dào)的列名Cursor.description隻是列名的第一個單詞,也(yě)就是說,如果您'as "x [datetime]"'在SQL中使用(yòng)類似的名稱,那麽我們将解析出所有内容,直到(dào)列名稱的第一個空(kōng)格爲止:列名稱将簡單地爲“x”。

sqlite3.connect(database[, timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements])

打開(kāi)到(dào)SQLite數據庫文(wén)件數據庫的連接。您可以使用(yòng)":memory:"打開(kāi)數據庫連接到(dào)駐留在RAM而不是磁盤上(shàng)的數據庫。

當數據庫被多個連接訪問時(shí),其中一個進程修改了(le)數據庫,SQLite數據庫被鎖定,直到(dào)該事(shì)務被提交。該超時(shí)參數指定連接應該多長時(shí)間等待鎖消失,直到(dào)引發異常。超時(shí)參數的默認值是5.0(五秒)。

有關isolation_level參數,請(qǐng)參閱對(duì)象的Connection.isolation_level屬性Connection。

SQLite本機僅支持TEXT,INTEGER,REAL,BLOB和(hé)NULL類型。如果你(nǐ)想使用(yòng)其他(tā)類型,你(nǐ)必須自(zì)己添加對(duì)它們的支持。該detect_types參數和(hé)使用(yòng)自(zì)定義轉換器與模塊級的注冊register_converter()功能(néng),讓你(nǐ)輕松做到(dào)這(zhè)一點。

detect_types默認爲0(即關閉,沒有類型檢測),您可以将其設置爲任意組合PARSE_DECLTYPES并PARSE_COLNAMES打開(kāi)類型檢測。

默認情況下(xià),sqlite3模塊将其Connection類用(yòng)于連接調用(yòng)。但(dàn)是,您可以繼承這(zhè)個Connection類,并connect()通過爲工(gōng)廠(chǎng)參數提供您的類來(lái)使用(yòng)您的類。

有關詳細信息,請(qǐng)參閱本手冊的SQLite和(hé)Python類型部分。

該sqlite3模塊在内部使用(yòng)一個語句緩存來(lái)避免SQL解析開(kāi)銷。如果要顯式設置爲連接緩存的語句數,可以設置cached_statements參數。目前實施的默認設置是緩存100條語句。

sqlite3.register_converter(typename, callable)

注冊一個可調用(yòng)的字符串,将數據庫中的字符串轉換爲自(zì)定義的Python類型。可調用(yòng)将爲類型爲typename的所有數據庫值調用(yòng)。賦予參數detect_types中的connect()該類型檢測是如何工(gōng)作(zuò)的功能(néng)。請(qǐng)注意,查詢中typename和(hé)類型的名稱必須匹配!

sqlite3.register_adapter(type, callable)

注冊可調用(yòng)以将自(zì)定義Python類型類型轉換爲SQLite支持的類型之一。可調用(yòng)callable接受Python值作(zuò)爲單個參數,并且必須返回以下(xià)類型的值:int,long,float,str(UTF-8編碼),unicode或緩沖區(qū)。

sqlite3.complete_statement(sql)

返回True如果字符串SQL包含由分号終止一個或多個完整的SQL語句。它不驗證SQL在語法上(shàng)是否正确,隻是沒有未關閉的字符串文(wén)本,并且語句以分号結尾。

這(zhè)可以用(yòng)來(lái)爲SQLite構建一個shell,如下(xià)例所示:

# 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 as e:

print "An error occurred:", e.args[0]

buffer = ""

con.close()

複制

sqlite3.enable_callback_tracebacks(flag)

默認情況下(xià),你(nǐ)不會(huì)在用(yòng)戶定義的函數,聚合,轉換器,授權者回調等中獲得任何回溯。如果你(nǐ)想調試它們,你(nǐ)可以調用(yòng)此标志設置爲的函數True。之後,你(nǐ)會(huì)從(cóng)回調中獲得回溯sys.stderr。用(yòng)于False再次禁用(yòng)該功能(néng)。

2.連接對(duì)象

class sqlite3.Connection

SQLite數據庫連接具有以下(xià)屬性和(hé)方法:

isolation_level

獲取或設置當前的隔離級别。None用(yòng)于自(zì)動提交模式或“延遲”,“立即”或“獨占”之一。有關更詳細的解釋,請(qǐng)參閱控制交易部分。

cursor(factory=Cursor)

遊标方法接受一個可選的參數工(gōng)廠(chǎng)。如果提供,它必須是可返回的實例Cursor或其子類。

commit()

此方法提交當前事(shì)務。如果您不調用(yòng)此方法,則自(zì)從(cóng)上(shàng)次調用(yòng)以來(lái)執行的任何操作(zuò)commit()都無法從(cóng)其他(tā)數據庫連接看(kàn)到(dào)。如果您想知(zhī)道(dào)爲什(shén)麽您沒有看(kàn)到(dào)您寫入數據庫的數據,請(qǐng)檢查您是否忘記調用(yòng)此方法。

rollback()

此方法回滾自(zì)上(shàng)次調用(yòng)以來(lái)對(duì)數據庫所做的任何更改commit()。

close()

這(zhè)将關閉數據庫連接。請(qǐng)注意,這(zhè)不會(huì)自(zì)動調用(yòng)commit()。如果您隻是在不commit()先調用(yòng)的情況下(xià)關閉數據庫連接,則更改将會(huì)丢失!

execute(sql[, parameters])

這(zhè)是一個非标準的快(kuài)捷方式,它通過調用(yòng)遊标方法創建中間遊标對(duì)象,然後execute使用(yòng)給定的參數調用(yòng)遊标的方法。

executemany(sql[, parameters])

這(zhè)是一個非标準的快(kuài)捷方式,它通過調用(yòng)遊标方法創建中間遊标對(duì)象,然後executemany使用(yòng)給定的參數調用(yòng)遊标的方法。

executescript(sql_script)

這(zhè)是一個非标準的快(kuài)捷方式,它通過調用(yòng)遊标方法創建中間遊标對(duì)象,然後executescript使用(yòng)給定的參數調用(yòng)遊标的方法。

create_function(name, num_params, func)

創建一個可以從(cóng)SQL語句中以後使用(yòng)下(xià)面的功能(néng)名稱的用(yòng)戶定義函數的名稱。num_params是函數接受的參數的個數,func是一個可調用(yòng)的Python,它被稱爲SQL函數。

該函數可以返回SQLite支持的任何類型:unicode,str,int,long,float,buffer和(hé)None。

例:

import sqlite3

import md5

def md5sum(t):

return md5.md5(t).hexdigest()

con = sqlite3.connect(":memory:")

con.create_function("md5", 1, md5sum)

cur = con.cursor()

cur.execute("select md5(?)", ("foo",))

print cur.fetchone()[0]

複制

create_aggregate(name, num_params, aggregate_class)

創建用(yòng)戶定義的聚合函數。

聚合類必須實現(xiàn)一個step方法,該方法接受參數num_params的數量,以及一個finalize将返回聚合的最終結果的方法。

該finalize方法可以返回SQLite支持的任何類型:unicode,str,int,long,float,buffer和(hé)None。

例:

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.create_aggregate("mysum", 1, MySum)

cur = con.cursor()

cur.execute("create table test(i)")

cur.execute("insert into test(i) values (1)")

cur.execute("insert into test(i) values (2)")

cur.execute("select mysum(i) from test")

print cur.fetchone()[0]

複制

create_collation(name, callable)

用(yòng)指定名稱創建一個排序規則并可調用(yòng)。可調用(yòng)将傳遞兩個字符串參數。如果第一個的順序低(dī)于第二個,則返回-1,如果順序相等,則返回0;如果第一個的順序高(gāo)于第二個,則返回1。請(qǐng)注意,這(zhè)會(huì)控制排序(SQL中的ORDER BY),因此您的比較不會(huì)影響其他(tā)SQL操作(zuò)。

請(qǐng)注意,可調用(yòng)函數将以Python字節串的形式獲取其參數,通常以UTF-8編碼。

以下(xià)示例顯示了(le)“錯誤方式”排序的自(zì)定義歸類:

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("create 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()

複制

要移除排序規則,請(qǐng)create_collation使用(yòng)None可調用(yòng)方式進行調用(yòng):

con.create_collation("reverse", None)

複制

interrupt()

您可以從(cóng)不同的線程調用(yòng)此方法以中止可能(néng)在連接上(shàng)執行的任何查詢。該查詢将中止,調用(yòng)者将得到(dào)一個異常。

set_authorizer(authorizer_callback)

這(zhè)個例程注冊一個回調。每次嘗試訪問數據庫中的一列表時(shí),都會(huì)調用(yòng)該回調。SQLITE_OK如果允許訪問,SQLITE_DENY則應該返回回調,如果整個SQL語句應該中止并出現(xiàn)錯誤,SQLITE_IGNORE并且該列應被視(shì)爲NULL值。這(zhè)些(xiē)常量在sqlite3模塊中可用(yòng)。

回調的第一個參數表示要授權哪種操作(zuò)。第二個和(hé)第三個參數将是參數或None取決于第一個參數。第四個參數是數據庫的名稱(“main”,“temp”等)(如果适用(yòng))。第五個參數是負責訪問嘗試的最内部觸發器或視(shì)圖的名稱,或者None如果此訪問嘗試直接來(lái)自(zì)輸入SQL代碼。

請(qǐng)參考SQLite文(wén)檔,了(le)解第一個參數的可能(néng)值以及第二個和(hé)第三個參數的含義,具體取決于第一個參數。sqlite3模塊中提供了(le)所有必需的常量。

set_progress_handler(handler, n)

這(zhè)個例程注冊一個回調。該回調函數針對(duì)SQLite虛拟機的每n個指令進行調用(yòng)。如果您想在長時(shí)間運行期間從(cóng)SQLite調用(yòng),例如更新GUI,這(zhè)很(hěn)有用(yòng)。

如果要清除以前安裝的任何進度處理(lǐ)程序,請(qǐng)使用(yòng)Nonefor 處理(lǐ)程序調用(yòng)該方法。

2.6版本中的新功能(néng)。

enable_load_extension(enabled)

此例程允許/禁止SQLite引擎從(cóng)共享庫加載SQLite擴展。SQLite擴展可以定義新的函數,聚合或全新的虛拟表實現(xiàn)。一個衆所周知(zhī)的擴展是與SQLite一起發布的全文(wén)搜索擴展。

可裝載的擴展名默認是禁用(yòng)的。見[1]。

2.7版本的新功能(néng)。

import sqlite3

con = sqlite3.connect(":memory:")

# enable extension loading

con.enable_load_extension(True)

# Load the fulltext search extension

con.execute("select load_extension('./fts3.so')")

# alternatively you can load the extension using an API call:

# con.load_extension("./fts3.so")

# disable extension laoding again

con.enable_load_extension(False)

# example from SQLite wiki

con.execute("create virtual table recipe using fts3(name, ingredients)")

con.executescript("""

insert into recipe (name, ingredients) values ('broccoli stew', 'broccoli peppers cheese tomatoes');

insert into recipe (name, ingredients) values ('pumpkin stew', 'pumpkin onions garlic celery');

insert into recipe (name, ingredients) values ('broccoli pie', 'broccoli cheese onions flour');

insert into recipe (name, ingredients) values ('pumpkin pie', 'pumpkin sugar flour butter');

""")

for row in con.execute("select rowid, name, ingredients from recipe where name match 'pie'"):

print row

複制

load_extension(path)

此例程從(cóng)共享庫中加載SQLite擴展。您必須先啓用(yòng)擴展加載,enable_load_extension()然後才能(néng)使用(yòng)此例程。

可裝載的擴展名默認是禁用(yòng)的。見[1]。

2.7版本的新功能(néng)。

row_factory

您可以将此屬性更改爲可接受的遊标,将遊标和(hé)原始行作(zuò)爲元組接受,并返回實際結果行。這(zhè)樣,您可以實現(xiàn)更高(gāo)級的返回結果方式,例如返回也(yě)可以按名稱訪問列的對(duì)象。

例:

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"]

複制

如果返回一個元組不夠,而你(nǐ)想要對(duì)列進行基于名稱的訪問,則應該考慮設置row_factory爲高(gāo)度優化的sqlite3.Row類型。Row提供基于索引和(hé)不區(qū)分大(dà)小(xiǎo)寫的基于名稱的訪問,幾乎沒有内存開(kāi)銷。它可能(néng)會(huì)比您自(zì)己的基于自(zì)定義字典的方法或甚至基于db_row的解決方案更好(hǎo)。

text_factory

使用(yòng)此屬性,您可以控制爲TEXT數據類型返回哪些(xiē)對(duì)象。默認情況下(xià),此屬性設置爲unicode,sqlite3模塊将返回Unicode對(duì)象TEXT。如果您想要返回字節串,可以将其設置爲str。

出于效率原因,還有一種方法可以僅返回非ASCII數據的Unicode對(duì)象,否則返回字節串。要激活它,請(qǐng)将此屬性設置爲sqlite3.OptimizedUnicode。

您還可以将其設置爲接受單個字符串參數并返回結果對(duì)象的任何其他(tā)可調用(yòng)對(duì)象。

有關說明(míng),請(qǐng)參閱以下(xià)示例代碼:

import sqlite3

con = sqlite3.connect(":memory:")

cur = con.cursor()

AUSTRIA = u"\xd6sterreich"

# by default, rows are returned as Unicode

cur.execute("select ?", (AUSTRIA,))

row = cur.fetchone()

assert row[0] == AUSTRIA

# but we can make sqlite3 always return bytestrings ...

con.text_factory = str

cur.execute("select ?", (AUSTRIA,))

row = cur.fetchone()

assert type(row[0]) is str

# the bytestrings will be encoded in UTF-8, unless you stored garbage in the

# database ...

assert row[0] == AUSTRIA.encode("utf-8")

# we can also implement a custom text_factory ...

# here we implement one that will ignore Unicode characters that cannot be

# decoded from 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]) is unicode

# sqlite3 offers a built-in 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 ?", (AUSTRIA,))

row = cur.fetchone()

assert type(row[0]) is unicode

cur.execute("select ?", ("Germany",))

row = cur.fetchone()

assert type(row[0]) is str

複制

total_changes

返回自(zì)數據庫連接打開(kāi)以來(lái)已修改,插入或删除的數據庫行總數。

iterdump

返回一個以SQL文(wén)本格式轉儲數據庫的叠代器。在保存内存數據庫以供日後恢複時(shí)很(hěn)有用(yòng)。該函數提供了(le)與sqlite3 shell中的.dump命令相同的功能(néng)。

2.6版本中的新功能(néng)。

例:

# Convert file existing_db.db to SQL dump file dump.sql

import sqlite3, os

con = sqlite3.connect('existing_db.db')

with open('dump.sql', 'w') as f:

for line in con.iterdump():

f.write('%s\n' % line)

複制

3.遊标對(duì)象

class sqlite3.Cursor

一個Cursor實例具有以下(xià)屬性和(hé)方法。

execute(sql[, parameters])

執行一條SQL語句。SQL語句可能(néng)是參數化的(即占位符而不是SQL文(wén)字)。該sqlite3模塊支持兩種占位符:問号(qmark樣式)和(hé)命名占位符(命名樣式)。

以下(xià)是兩種樣式的示例:

import sqlite3

con = sqlite3.connect(":memory:")

cur = con.cursor()

cur.execute("create table people (name_last, age)")

who = "Yeltsin"

age = 72

# This is the qmark style:

cur.execute("insert into people values (?, ?)", (who, age))

# And this is the named style:

cur.execute("select * from people where name_last=:who and age=:age", {"who": who, "age": age})

print cur.fetchone()

複制

execute()隻會(huì)執行一條SQL語句。如果您嘗試使用(yòng)它執行多個語句,則會(huì)引發警告。使用(yòng)executescript(),如果你(nǐ)想用(yòng)一個調用(yòng)執行多個SQL語句。

executemany(sql, seq_of_parameters)

針對(duì)在序列sql中找到(dào)的所有參數序列或映射執行SQL命令。該sqlite3模塊還允許使用(yòng)叠代器産生參數而不是序列。

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()

複制

以下(xià)是使用(yòng)生成器的較簡單示例:

import sqlite3

import string

def char_generator():

for c in string.lowercase:

yield (c,)

con = sqlite3.connect(":memory:")

cur = con.cursor()

cur.execute("create table characters(c)")

cur.executemany("insert into characters(c) values (?)", char_generator())

cur.execute("select c from characters")

print cur.fetchall()

複制

executescript(sql_script)

這(zhè)是一次執行多個SQL語句的非标準便利方法。它首先發布一個COMMIT語句,然後執行它作(zuò)爲參數獲取的SQL腳本。

sql_script可以是一個字節串或一個Unicode字符串。

例:

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

);

""")

複制

fetchone()

獲取查詢結果集的下(xià)一行,返回單個序列,或者None沒有更多數據可用(yòng)時(shí)。

fetchmany([size=cursor.arraysize])

獲取查詢結果的下(xià)一組行,并返回一個列表。沒有更多行可用(yòng)時(shí)返回空(kōng)列表。

每次調用(yòng)要獲取的行數由size參數指定。如果沒有給出,遊标的數組大(dà)小(xiǎo)決定了(le)要獲取的行數。該方法應該嘗試獲取大(dà)小(xiǎo)參數所指示的行數。如果由于指定的行數不可用(yòng)而無法執行此操作(zuò),則可能(néng)會(huì)返回更少的行。

請(qǐng)注意,大(dà)小(xiǎo)參數涉及性能(néng)方面的考慮因素。爲了(le)獲得最佳性能(néng),通常最好(hǎo)使用(yòng)arraysize屬性。如果使用(yòng)size參數,那麽最好(hǎo)從(cóng)一次fetchmany()調用(yòng)到(dào)下(xià)一次調用(yòng)保持相同的值。

fetchall()

獲取查詢結果的所有(剩餘)行,并返回一個列表。請(qǐng)注意,遊标的arraysize屬性可能(néng)會(huì)影響此操作(zuò)的性能(néng)。沒有行可用(yòng)時(shí)返回空(kōng)列表。

rowcount

雖然模塊的Cursor類sqlite3實現(xiàn)了(le)這(zhè)個屬性,但(dàn)數據庫引擎自(zì)己對(duì)确定“受影響的行”/“所選擇的行”的支持是古怪的。

對(duì)于executemany()陳述,修改的數量被總結成rowcount。

按照Python DB API Spec的要求,rowcount如果executeXX()遊标上(shàng)沒有執行任何操作(zuò),或者上(shàng)一次操作(zuò)的行數不能(néng)被界面确定,則屬性“爲-1 ”。這(zhè)包括SELECT語句,因爲我們無法确定查詢産生的行數,直到(dào)獲取所有行。

使用(yòng)3.6.5之前的SQLite版本,rowcount如果您DELETE FROM table沒有任何條件,則設置爲0 。

lastrowid

此隻讀屬性提供最後修改行的rowid。隻有在您INSERT使用(yòng)該execute()方法發布聲明(míng)時(shí)才會(huì)設置。對(duì)于調用(yòng)以外(wài)INSERT或executemany()調用(yòng)時(shí)的操作(zuò),lastrowid設置爲None。

description

此隻讀屬性提供最後一個查詢的列名稱。爲了(le)與Python DB API保持兼容,它會(huì)爲每個元組的最後六項所在的每列返回一個7元組None。

它被設置爲SELECT沒有任何匹配行的語句。

connection

這(zhè)個隻讀屬性提供Connection了(le)Cursor對(duì)象使用(yòng)的SQLite數據庫。一個Cursor通過調用(yòng)創建的對(duì)象con.cursor()将有一個connection引用(yòng)屬性CON:

>>> con = sqlite3.connect(":memory:")

>>> cur = con.cursor()

>>> cur.connection == con

True

複制

4.行對(duì)象

class sqlite3.Row

Row實例用(yòng)作(zuò)一個高(gāo)度優化的row_factory用(yòng)于Connection對(duì)象。它試圖模仿大(dà)部分功能(néng)中的元組。

它支持按列名和(hé)索引進行映射訪問,叠代,表示,相等性測試和(hé)len()。

如果兩個Row對(duì)象具有完全相同的列并且它們的成員相等,則它們相等。

在版本2.6中進行了(le)更改:添加了(le)叠代和(hé)等式(hashability)。

keys()

此方法返回列名稱的列表。在查詢之後,它立即成爲每個元組的第一個成員Cursor.description。

2.6版本中的新功能(néng)。

我們假設我們按照上(shàng)面給出的例子初始化一個表格:

conn = sqlite3.connect(":memory:")

c = conn.cursor()

c.execute('''create table stocks

(date text, trans text, symbol text,

qty real, price real)''')

c.execute("""insert into stocks

values ('2006-01-05','BUY','RHAT',100,35.14)""")

conn.commit()

c.close()

複制

現(xiàn)在我們插入Row:

>>> conn.row_factory = sqlite3.Row

>>> c = conn.cursor()

>>> c.execute('select * from stocks')

<sqlite3.Cursor object at 0x7f4e7dd8fa80>

>>> r = c.fetchone()

>>> type(r)

<type 'sqlite3.Row'>

>>> r

(u'2006-01-05', u'BUY', u'RHAT', 100.0, 35.14)

>>> len(r)

5

>>> r[2]

u'RHAT'

>>> r.keys()

['date', 'trans', 'symbol', 'qty', 'price']

>>> r['qty']

100.0

>>> for member in r:

... print member

...

2006-01-05

BUY

RHAT

100.0

35.14

複制

5. SQLite和(hé)Python類型

5.1。介紹

SQLite的原生支持以下(xià)幾種類型:NULL,INTEGER,REAL,TEXT,BLOB。

因此可以将以下(xià)Python類型發送給SQLite,而不會(huì)有任何問題:

Python類型

SQLite類型

沒有

空(kōng)值

INT

整數

long

整數

浮動

真實

str(UTF8編碼)

文(wén)本

統一

文(wén)本

緩沖

BLOB

這(zhè)是默認情況下(xià)SQLite類型轉換爲Python類型的方式:

SQLite類型

Python類型

空(kōng)值

沒有

整數

int或long,這(zhè)取決于大(dà)小(xiǎo)

真實

浮動

文(wén)本

取決于text_factory,默認情況下(xià)是unicode

BLOB

緩沖

sqlite3模塊的類型系統可以通過兩種方式進行擴展:可以通過對(duì)象适配将其他(tā)Python類型存儲在SQLite數據庫中,并且可以讓sqlite3模塊通過轉換器将SQLite類型轉換爲不同的Python類型。

5.2。使用(yòng)适配器在SQLite數據庫中存儲其他(tā)Python類型

如前所述,SQLite本身隻支持一組有限的類型。要将其他(tā)Python類型與SQLite一起使用(yòng),您必須将它們調整爲sqlite3模塊支持的SQLite類型之一:NoneType,int,long,float,str,unicode,buffer之一。

有兩種方法可以使sqlite3模塊将自(zì)定義的Python類型改爲支持的類型之一。

5.2.1。讓你(nǐ)的對(duì)象适應自(zì)己

如果你(nǐ)自(zì)己寫課程,這(zhè)是一個很(hěn)好(hǎo)的方法。假設你(nǐ)有這(zhè)樣的課程:

class Point(object):

def __init__(self, x, y):

self.x, self.y = x, y

複制

現(xiàn)在您想要将該點存儲在單個SQLite列中。首先,您必須首先選擇一種支持的類型來(lái)表示該點。我們隻需使用(yòng)str并使用(yòng)分号分隔坐(zuò)标。然後你(nǐ)需要給你(nǐ)的班級一個__conform__(self, protocol)必須返回轉換後的值的方法。參數協議(yì)将會(huì)是PrepareProtocol。

import sqlite3

class Point(object):

def __init__(self, x, y):

self.x, self.y = x, y

def __conform__(self, protocol):

if protocol is sqlite3.PrepareProtocol:

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

con = sqlite3.connect(":memory:")

cur = con.cursor()

p = Point(4.0, -3.2)

cur.execute("select ?", (p,))

print cur.fetchone()[0]

複制

5.2.2。注冊可調用(yòng)的适配器

另一種可能(néng)性是創建一個将類型轉換爲字符串表示并将函數注冊的函數register_adapter()。

注釋

适應的類型/類别必須是新式類别,即它必須具有object作(zuò)爲其基礎之一。

import sqlite3

class Point(object):

def __init__(self, x, y):

self.x, self.y = x, y

def adapt_point(point):

return "%f;%f" % (point.x, point.y)

sqlite3.register_adapter(Point, adapt_point)

con = sqlite3.connect(":memory:")

cur = con.cursor()

p = Point(4.0, -3.2)

cur.execute("select ?", (p,))

print cur.fetchone()[0]

複制

該sqlite3模塊有兩個用(yòng)于Python内置datetime.date和(hé)datetime.datetime類型的默認适配器。現(xiàn)在讓我們假設我們想存儲datetime.datetime不是ISO表示的對(duì)象,而是作(zuò)爲一個Unix時(shí)間戳。

import sqlite3

import datetime, time

def adapt_datetime(ts):

return time.mktime(ts.timetuple())

sqlite3.register_adapter(datetime.datetime, adapt_datetime)

con = sqlite3.connect(":memory:")

cur = con.cursor()

now = datetime.datetime.now()

cur.execute("select ?", (now,))

print cur.fetchone()[0]

複制

5.3。将SQLite值轉換爲自(zì)定義Python類型

編寫适配器可讓您将自(zì)定義Python類型發送到(dào)SQLite。但(dàn)爲了(le)讓它變得非常有用(yòng),我們需要讓Python到(dào)SQLite來(lái)Python的往返工(gōng)作(zuò)。

輸入轉換器。

讓我們回到(dào)Point課堂上(shàng)。我們将通過分号分隔的x和(hé)y坐(zuò)标存儲爲SQLite中的字符串。

首先,我們将定義一個轉換器函數,該函數接受字符串作(zuò)爲參數并Point從(cóng)中構造一個對(duì)象。

注意

無論使用(yòng)哪種數據類型将值發送給SQLite,轉換器函數總是使用(yòng)字符串調用(yòng)。

def convert_point(s):

x, y = map(float, s.split(";"))

return Point(x, y)

複制

現(xiàn)在您需要讓sqlite3模塊知(zhī)道(dào)您從(cóng)數據庫中選擇的内容實際上(shàng)是一個點。有兩種方法可以做到(dào)這(zhè)一點:

隐式地通過聲明(míng)的類型

顯式地通過列名稱

這(zhè)兩種方法在節模塊函數和(hé)常數描述,在用(yòng)于常量的條目PARSE_DECLTYPES和(hé)PARSE_COLNAMES。

以下(xià)示例說明(míng)了(le)這(zhè)兩種方法。

import sqlite3

class Point(object):

def __init__(self, x, y):

self.x, self.y = x, y

def __repr__(self):

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

def adapt_point(point):

return "%f;%f" % (point.x, point.y)

def convert_point(s):

x, y = map(float, s.split(";"))

return Point(x, y)

# Register the adapter

sqlite3.register_adapter(Point, adapt_point)

# Register the converter

sqlite3.register_converter("point", convert_point)

p = Point(4.0, -3.2)

#########################

# 1) Using declared types

con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)

cur = con.cursor()

cur.execute("create table test(p point)")

cur.execute("insert into test(p) values (?)", (p,))

cur.execute("select p from test")

print "with declared types:", cur.fetchone()[0]

cur.close()

con.close()

#######################

# 1) Using column names

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

cur = con.cursor()

cur.execute("create table test(p)")

cur.execute("insert into test(p) values (?)", (p,))

cur.execute('select p as "p [point]" from test')

print "with column names:", cur.fetchone()[0]

cur.close()

con.close()

複制

5.4。默認适配器和(hé)轉換器

日期時(shí)間模塊中有日期和(hé)日期時(shí)間類型的默認适配器。它們将作(zuò)爲ISO日期/ ISO時(shí)間戳發送到(dào)SQLite。

默認轉換器的名稱爲“date”,datetime.date名稱爲“timestamp” datetime.datetime。

這(zhè)樣,在大(dà)多數情況下(xià),您可以使用(yòng)Python中的日期/時(shí)間戳,而不需要額外(wài)的操作(zuò)。适配器的格式也(yě)與實驗性SQLite日期/時(shí)間函數兼容。

以下(xià)示例演示了(le)這(zhè)一點。

import sqlite3

import datetime

con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)

cur = con.cursor()

cur.execute("create table test(d date, ts timestamp)")

today = datetime.date.today()

now = datetime.datetime.now()

cur.execute("insert into test(d, ts) values (?, ?)", (today, now))

cur.execute("select d, ts from test")

row = cur.fetchone()

print today, "=>", row[0], type(row[0])

print now, "=>", row[1], type(row[1])

cur.execute('select current_date as "d [date]", current_timestamp as "ts [timestamp]"')

row = cur.fetchone()

print "current_date", row[0], type(row[0])

print "current_timestamp", row[1], type(row[1])

複制

如果存儲在SQLite中的時(shí)間戳記的分數部分長于6個數字,則其值将被時(shí)間戳轉換器截斷爲微秒精度。

6.控制交易

默認情況下(xià),sqlite3模塊在數據修改語言(DML)語句(即INSERT/ UPDATE/ DELETE/ REPLACE)之前隐式打開(kāi)事(shì)務,并在非DML非查詢語句(即非SELECT上(shàng)述任何内容)之前隐式提交事(shì)務。

所以,如果你(nǐ)是一個事(shì)務中,并發出這(zhè)樣的命令CREATE TABLE ...,VACUUM,PRAGMA,該sqlite3模塊将隐式執行該命令之前提交。這(zhè)樣做有兩個原因。首先,這(zhè)些(xiē)命令中的某些(xiē)命令在事(shì)務中不起作(zuò)用(yòng)。另一個原因是sqlite3需要跟蹤事(shì)務狀态(如果事(shì)務處于活動狀态)。

你(nǐ)可以控制BEGINsqlite3通過調用(yòng)isolation_level參數connect()或通過isolation_level連接屬性隐式執行哪種語句(或者根本不執行)。

如果您想要自(zì)動提交模式,請(qǐng)設置isolation_level爲None。

否則,将其保留爲默認值,這(zhè)将導緻一個簡單的“BEGIN”語句,或将其設置爲SQLite支持的隔離級别之一:“DEFERRED”,“IMMEDIATE”或“EXCLUSIVE”。

7.高(gāo)效地使用(yòng)sqlite3

7.1。使用(yòng)快(kuài)捷方式

使用(yòng)非标準的execute(),executemany()并且executescript()該方法的Connection對(duì)象,您的代碼可以更簡潔,因爲你(nǐ)不必創建(通常是多餘的)書面Cursor明(míng)确對(duì)象。相反,Cursor對(duì)象是隐式創建的,這(zhè)些(xiē)快(kuài)捷方法返回遊标對(duì)象。這(zhè)樣,您可以執行一個SELECT語句并直接使用(yòng)該Connection對(duì)象上(shàng)的一次調用(yòng)直接對(duì)其進行叠代。

import sqlite3

persons = [

("Hugo", "Boss"),

("Calvin", "Klein")

]

con = sqlite3.connect(":memory:")

# Create the table

con.execute("create table person(firstname, lastname)")

# Fill the table

con.executemany("insert into person(firstname, lastname) values (?, ?)", persons)

# Print the table contents

for row in con.execute("select firstname, lastname from person"):

print row

print "I just deleted", con.execute("delete from person").rowcount, "rows"

複制

7.2。按名稱而不是按索引訪問列

該sqlite3模塊的一個有用(yòng)功能(néng)是sqlite3.Row設計(jì)用(yòng)作(zuò)行工(gōng)廠(chǎng)的内置類。

使用(yòng)此類包裝的行可以通過索引(如元組)訪問,也(yě)可以通過名稱不區(qū)分大(dà)小(xiǎo)寫:

import sqlite3

con = sqlite3.connect(":memory:")

con.row_factory = sqlite3.Row

cur = con.cursor()

cur.execute("select 'John' as name, 42 as age")

for row in cur:

assert row[0] == row["name"]

assert row["name"] == row["nAmE"]

assert row[1] == row["age"]

assert row[1] == row["AgE"]

複制

7.3。使用(yòng)連接作(zuò)爲上(shàng)下(xià)文(wén)管理(lǐ)器

2.6版本中的新功能(néng)。

連接對(duì)象可以用(yòng)作(zuò)自(zì)動提交或回滾事(shì)務的上(shàng)下(xià)文(wén)管理(lǐ)器。如果發生異常,交易将回滾; 否則,交易承諾:

import sqlite3

con = sqlite3.connect(":memory:")

con.execute("create table person (id integer primary key, firstname varchar unique)")

# Successful, con.commit() is called automatically afterwards

with con:

con.execute("insert into person(firstname) values (?)", ("Joe",))

# con.rollback() is called after the with block finishes with an exception, the

# exception is still raised and must be caught

try:

with con:

con.execute("insert into person(firstname) values (?)", ("Joe",))

except sqlite3.IntegrityError:

print "couldn't add Joe twice"

複制

8.常見問題

8.1。多線程

較舊的SQLite版本在共享線程之間的連接時(shí)遇到(dào)了(le)問題。這(zhè)就是爲什(shén)麽Python模塊不允許在線程之間共享連接和(hé)遊标的原因。如果你(nǐ)仍然嘗試這(zhè)樣做,你(nǐ)将在運行時(shí)得到(dào)一個異常。

唯一的例外(wài)是調用(yòng)該interrupt()方法,這(zhè)隻有在從(cóng)不同的線程調用(yòng)時(shí)才有意義。

1

(1,2)默認情況下(xià),sqlite3模塊不是由可加載擴展支持構建的,因爲某些(xiē)平台(特别是Mac OS X)具有無需此功能(néng)編譯的SQLite庫。要獲得可加載的擴展支持,您必須修改setup.py并删除設置SQLITE_OMIT_LOAD_EXTENSION的行。

網站(zhàn)建設開(kāi)發|APP設計(jì)開(kāi)發|小(xiǎo)程序建設開(kāi)發
下(xià)一篇:數據持久性 | Data Persistence whichdb
上(shàng)一篇:數據持久性 | Data Persistence shelve