sqlite3
— 適用於 SQLite 資料庫的 DB-API 2.0 介面¶
原始碼: Lib/sqlite3/
SQLite 是一個 C 庫,它提供了一個輕量級的基於磁碟的資料庫,不需要單獨的伺服器程序,並允許使用 SQL 查詢語言的非標準變體來訪問資料庫。一些應用程式可以使用 SQLite 進行內部資料儲存。還可以使用 SQLite 構建應用程式原型,然後將程式碼移植到更大的資料庫,例如 PostgreSQL 或 Oracle。
sqlite3
模組由 Gerhard Häring 編寫。它提供了一個符合 PEP 249 描述的 DB-API 2.0 規範的 SQL 介面,並且需要 SQLite 3.15.2 或更新版本。
本文件包含四個主要部分
參見
- https://www.sqlite.org
SQLite 網頁;文件描述了所支援 SQL 方言的語法和可用資料型別。
- https://w3schools.tw/sql/
用於學習 SQL 語法的教程、參考和示例。
- PEP 249 - 資料庫 API 規範 2.0
由 Marc-André Lemburg 編寫的 PEP。
教程¶
在本教程中,您將使用基本的 sqlite3
功能建立一個 Monty Python 電影資料庫。它假定您對資料庫概念有基本瞭解,包括 遊標 和 事務。
首先,我們需要建立一個新資料庫並開啟一個數據庫連線,以允許 sqlite3
對其進行操作。呼叫 sqlite3.connect()
在當前工作目錄中建立與資料庫 tutorial.db
的連線,如果它不存在則隱式建立它
import sqlite3
con = sqlite3.connect("tutorial.db")
返回的 Connection
物件 con
表示與磁碟資料庫的連線。
為了執行 SQL 語句並從 SQL 查詢中獲取結果,我們需要使用資料庫遊標。呼叫 con.cursor()
來建立 Cursor
cur = con.cursor()
現在我們已經有了資料庫連線和遊標,我們可以建立一個數據庫表 movie
,其中包含標題、釋出年份和評分的列。為簡單起見,我們可以在表宣告中只使用列名——由於 SQLite 的 靈活型別 功能,指定資料型別是可選的。透過呼叫 cur.execute(...)
執行 CREATE TABLE
語句
cur.execute("CREATE TABLE movie(title, year, score)")
我們可以透過查詢 SQLite 內建的 sqlite_master
表來驗證新表是否已建立,該表現在應該包含 movie
表定義的條目(有關詳細資訊,請參閱 Schema Table)。透過呼叫 cur.execute(...)
執行該查詢,將結果分配給 res
,然後呼叫 res.fetchone()
來獲取結果行
>>> res = cur.execute("SELECT name FROM sqlite_master")
>>> res.fetchone()
('movie',)
我們可以看到表已經建立,因為查詢返回一個包含表名的 元組
。如果我們查詢 sqlite_master
以查詢不存在的表 spam
,res.fetchone()
將返回 None
>>> res = cur.execute("SELECT name FROM sqlite_master WHERE name='spam'")
>>> res.fetchone() is None
True
現在,透過執行 INSERT
語句,再次透過呼叫 cur.execute(...)
,新增作為 SQL 字面量提供的兩行資料
cur.execute("""
INSERT INTO movie VALUES
('Monty Python and the Holy Grail', 1975, 8.2),
('And Now for Something Completely Different', 1971, 7.5)
""")
INSERT
語句隱式地開啟一個事務,該事務需要在更改儲存到資料庫之前提交(有關詳細資訊,請參閱 事務控制)。在連線物件上呼叫 con.commit()
來提交事務
con.commit()
我們可以透過執行 SELECT
查詢來驗證資料是否已正確插入。使用現在熟悉的 cur.execute(...)
將結果分配給 res
,然後呼叫 res.fetchall()
返回所有結果行
>>> res = cur.execute("SELECT score FROM movie")
>>> res.fetchall()
[(8.2,), (7.5,)]
結果是一個包含兩個 tuple
的 list
,每行一個,每個 tuple
包含該行的 score
值。
現在,透過呼叫 cur.executemany(...)
插入另外三行
data = [
("Monty Python Live at the Hollywood Bowl", 1982, 7.9),
("Monty Python's The Meaning of Life", 1983, 7.5),
("Monty Python's Life of Brian", 1979, 8.0),
]
cur.executemany("INSERT INTO movie VALUES(?, ?, ?)", data)
con.commit() # Remember to commit the transaction after executing INSERT.
注意,?
佔位符用於將 data
繫結到查詢。始終使用佔位符而不是 字串格式化 將 Python 值繫結到 SQL 語句,以避免 SQL 注入攻擊(有關詳細資訊,請參閱 如何使用佔位符繫結 SQL 查詢中的值)。
我們可以透過執行 SELECT
查詢來驗證新行是否已插入,這次迭代查詢結果
>>> for row in cur.execute("SELECT year, title FROM movie ORDER BY year"):
... print(row)
(1971, 'And Now for Something Completely Different')
(1975, 'Monty Python and the Holy Grail')
(1979, "Monty Python's Life of Brian")
(1982, 'Monty Python Live at the Hollywood Bowl')
(1983, "Monty Python's The Meaning of Life")
每行是一個包含兩個專案的 元組
(year, title)
,與查詢中選擇的列匹配。
最後,透過呼叫 con.close()
關閉現有連線,開啟新連線,建立新遊標,然後查詢資料庫,驗證資料庫是否已寫入磁碟
>>> con.close()
>>> new_con = sqlite3.connect("tutorial.db")
>>> new_cur = new_con.cursor()
>>> res = new_cur.execute("SELECT title, year FROM movie ORDER BY score DESC")
>>> title, year = res.fetchone()
>>> print(f'The highest scoring Monty Python movie is {title!r}, released in {year}')
The highest scoring Monty Python movie is 'Monty Python and the Holy Grail', released in 1975
>>> new_con.close()
您現在已經使用 sqlite3
模組建立了一個 SQLite 資料庫,並以多種方式插入資料並從中檢索值。
參見
參考¶
模組函式¶
- sqlite3.connect(database, timeout=5.0, detect_types=0, isolation_level='DEFERRED', check_same_thread=True, factory=sqlite3.Connection, cached_statements=128, uri=False, *, autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL)¶
開啟與 SQLite 資料庫的連線。
- 引數:
database (類路徑物件) – 要開啟的資料庫檔案的路徑。您可以傳遞
":memory:"
以建立 僅存在於記憶體中的 SQLite 資料庫,並開啟與其的連線。timeout (浮點數) – 當表被鎖定後,連線應該等待多少秒才引發
OperationalError
。如果另一個連線開啟事務以修改表,該表將被鎖定直到事務提交。預設五秒。detect_types (整數) – 控制如何查詢 SQLite 不原生支援 的資料型別,以使用
register_converter()
註冊的轉換器將其轉換為 Python 型別。將其設定為PARSE_DECLTYPES
和PARSE_COLNAMES
的任意組合(使用|
,按位或)以啟用此功能。如果同時設定了這兩個標誌,則列名優先於宣告的型別。預設情況下 (0
),型別檢測被停用。isolation_level (字串 | None) – 控制舊式事務處理行為。有關更多資訊,請參閱
Connection.isolation_level
和 透過 isolation_level 屬性進行事務控制。可以是"DEFERRED"
(預設)、"EXCLUSIVE"
或"IMMEDIATE"
;或者None
以停用隱式開啟事務。除非Connection.autocommit
設定為LEGACY_TRANSACTION_CONTROL
(預設值),否則無效。check_same_thread (布林值) – 如果為
True
(預設),則如果資料庫連線被建立它的執行緒以外的執行緒使用,將引發ProgrammingError
。如果為False
,則連線可以在多個執行緒中訪問;使用者可能需要序列化寫入操作以避免資料損壞。有關更多資訊,請參閱threadsafety
。factory (Connection) –
Connection
的自定義子類,用於建立連線,而不是預設的Connection
類。cached_statements (整數) –
sqlite3
應為此連線內部快取的語句數,以避免解析開銷。預設情況下為 128 條語句。uri (布林值) – 如果設定為
True
,則 *database* 將被解釋為包含檔案路徑和可選查詢字串的 URI。方案部分 *必須* 是"file:"
,並且路徑可以是相對的或絕對的。查詢字串允許將引數傳遞給 SQLite,從而啟用各種 如何使用 SQLite URI。autocommit (布林值) – 控制 PEP 249 事務處理行為。有關更多資訊,請參閱
Connection.autocommit
和 透過 autocommit 屬性進行事務控制。autocommit 當前預設為LEGACY_TRANSACTION_CONTROL
。在未來的 Python 版本中,預設值將更改為False
。
- 返回型別:
引發一個 審計事件
sqlite3.connect
,引數為database
。引發一個 審計事件
sqlite3.connect/handle
,引數為connection_handle
。3.4 版本中已更改: 添加了 uri 引數。
3.7 版本中已更改: database 現在也可以是 類路徑物件,而不僅僅是字串。
3.10 版本中已更改: 添加了
sqlite3.connect/handle
審計事件。3.12 版本中已更改: 添加了 autocommit 引數。
3.13 版本中已更改: 引數 timeout, detect_types, isolation_level, check_same_thread, factory, cached_statements 和 uri 的位置引數用法已棄用。它們將在 Python 3.15 中成為僅限關鍵字的引數。
- sqlite3.complete_statement(statement)¶
如果字串 statement 似乎包含一個或多個完整的 SQL 語句,則返回
True
。除了檢查沒有未閉合的字串字面量以及語句以分號終止之外,不執行任何句法驗證或解析。例如:
>>> sqlite3.complete_statement("SELECT foo FROM bar;") True >>> sqlite3.complete_statement("SELECT foo") False
此函式在命令列輸入期間可能很有用,用於確定輸入的文字是否似乎構成了一個完整的 SQL 語句,或者在呼叫
execute()
之前是否需要額外輸入。有關實際用法,請參閱 Lib/sqlite3/__main__.py 中的
runsource()
。
- sqlite3.enable_callback_tracebacks(flag, /)¶
啟用或停用回調回溯。預設情況下,您不會在使用者定義函式、聚合、轉換器、授權器回撥等中獲得任何回溯。如果您想除錯它們,可以呼叫此函式並將 *flag* 設定為
True
。之後,您將在sys.stderr
上獲取回撥的回溯。使用False
再次停用該功能。備註
使用者定義函式回撥中的錯誤將作為不可引發的異常記錄。使用
unraisable hook handler
來檢查失敗的回撥。
- sqlite3.register_adapter(type, adapter, /)¶
註冊一個 *adapter* 可呼叫物件,用於將 Python 型別 *type* 適配為 SQLite 型別。介面卡以 *type* 型別的 Python 物件作為其唯一引數呼叫,並且必須返回 SQLite 原生理解的型別 的值。
模組常量¶
- sqlite3.LEGACY_TRANSACTION_CONTROL¶
將
autocommit
設定為此常量以選擇舊式(Python 3.12 之前)事務控制行為。有關更多資訊,請參閱 透過 isolation_level 屬性進行事務控制。
- sqlite3.PARSE_DECLTYPES¶
將此標誌值傳遞給
connect()
的 *detect_types* 引數,以使用每列的宣告型別查詢轉換函式。型別在建立資料庫表時宣告。sqlite3
將使用宣告型別中的第一個單詞作為轉換器字典鍵來查詢轉換函式。例如CREATE TABLE test( i integer primary key, ! will look up a converter named "integer" p point, ! will look up a converter named "point" n number(10) ! will look up a converter named "number" )
此標誌可以與
PARSE_COLNAMES
使用|
(按位或)運算子結合使用。備註
生成欄位(例如
MAX(p)
)作為str
返回。使用PARSE_COLNAMES
為此類查詢強制執行型別。
- sqlite3.PARSE_COLNAMES¶
將此標誌值傳遞給
connect()
的 *detect_types* 引數,以使用從查詢列名解析出的型別名作為轉換器字典鍵來查詢轉換函式。查詢列名必須用雙引號 ("
) 包裹,型別名必須用方括號 ([]
) 包裹。SELECT MAX(p) as "p [point]" FROM test; ! will look up converter "point"
此標誌可以與
PARSE_DECLTYPES
使用|
(按位或)運算子結合使用。
- sqlite3.SQLITE_OK¶
- sqlite3.SQLITE_DENY¶
- sqlite3.SQLITE_IGNORE¶
應由傳遞給
Connection.set_authorizer()
的 *authorizer_callback* 可呼叫物件 返回的標誌,以指示是否允許訪問 (
SQLITE_OK
),SQL 語句應因錯誤而中止 (
SQLITE_DENY
)該列應被視為
NULL
值 (SQLITE_IGNORE
)
- sqlite3.apilevel¶
表示支援的 DB-API 級別的字串常量。DB-API 要求。硬編碼為
"2.0"
。
- sqlite3.paramstyle¶
表示
sqlite3
模組期望的引數標記格式型別的字串常量。DB-API 要求。硬編碼為"qmark"
。備註
還支援
named
DB-API 引數樣式。
- sqlite3.threadsafety¶
DB-API 2.0 要求的整數常量,表示
sqlite3
模組支援的執行緒安全級別。此屬性根據底層 SQLite 庫編譯時使用的預設 執行緒模式 設定。SQLite 執行緒模式有單執行緒:在此模式下,所有互斥體都被停用,SQLite 在一次只能有一個執行緒中使用是不安全的。
多執行緒:在此模式下,只要沒有單個數據庫連線同時在兩個或更多執行緒中使用,SQLite 就可以被多個執行緒安全地使用。
序列化:在序列化模式下,SQLite 可以被多個執行緒安全地使用,沒有任何限制。
SQLite 執行緒模式到 DB-API 2.0 執行緒安全級別的對映如下
SQLite 執行緒模式
DB-API 2.0 含義
單執行緒
0
0
執行緒不能共享模組
多執行緒
1
2
執行緒可以共享模組,但不能共享連線
序列化
3
1
執行緒可以共享模組、連線和遊標
3.11 版本中已更改: 動態設定 threadsafety 而不是硬編碼為
1
。
- sqlite3.SQLITE_DBCONFIG_DEFENSIVE¶
- sqlite3.SQLITE_DBCONFIG_DQS_DDL¶
- sqlite3.SQLITE_DBCONFIG_DQS_DML¶
- sqlite3.SQLITE_DBCONFIG_ENABLE_FKEY¶
- sqlite3.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER¶
- sqlite3.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION¶
- sqlite3.SQLITE_DBCONFIG_ENABLE_QPSG¶
- sqlite3.SQLITE_DBCONFIG_ENABLE_TRIGGER¶
- sqlite3.SQLITE_DBCONFIG_ENABLE_VIEW¶
- sqlite3.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE¶
- sqlite3.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT¶
- sqlite3.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE¶
- sqlite3.SQLITE_DBCONFIG_RESET_DATABASE¶
- sqlite3.SQLITE_DBCONFIG_TRIGGER_EQP¶
- sqlite3.SQLITE_DBCONFIG_TRUSTED_SCHEMA¶
- sqlite3.SQLITE_DBCONFIG_WRITABLE_SCHEMA¶
這些常量用於
Connection.setconfig()
和getconfig()
方法。這些常量的可用性取決於 Python 編譯時使用的 SQLite 版本。
3.12 新版功能.
參見
- https://www.sqlite.org/c3ref/c_dbconfig_defensive.html
SQLite 文件:資料庫連線配置選項
自 3.12 版本棄用,在 3.14 版本中刪除: version
和 version_info
常量。
連線物件¶
- class sqlite3.Connection¶
每個開啟的 SQLite 資料庫都由一個
Connection
物件表示,該物件使用sqlite3.connect()
建立。它們的主要目的是建立Cursor
物件和 事務控制。3.13 版本中已更改: 如果在
Connection
物件被刪除之前未呼叫close()
,則會發出ResourceWarning
。SQLite 資料庫連線具有以下屬性和方法
- cursor(factory=Cursor)¶
建立並返回一個
Cursor
物件。遊標方法接受一個可選引數 *factory*。如果提供,它必須是一個 可呼叫物件,返回Cursor
或其子類的例項。
- blobopen(table, column, rowid, /, *, readonly=False, name='main')¶
開啟一個
Blob
控制代碼以操作現有 BLOB。- 引數:
- 引發:
OperationalError – 當嘗試在
WITHOUT ROWID
表中開啟 blob 時。- 返回型別:
備註
Blob 大小不能使用
Blob
類更改。使用 SQL 函式zeroblob
建立具有固定大小的 blob。在 3.11 版本中新增。
- commit()¶
將所有待處理的事務提交到資料庫。如果
autocommit
為True
,或者沒有開啟的事務,則此方法不執行任何操作。如果autocommit
為False
,並且此方法提交了待處理的事務,則會隱式開啟一個新事務。
- rollback()¶
回滾到任何待處理事務的開始。如果
autocommit
為True
,或者沒有開啟的事務,則此方法不執行任何操作。如果autocommit
為False
,並且此方法回滾了待處理的事務,則會隱式開啟一個新事務。
- close()¶
關閉資料庫連線。如果
autocommit
為False
,則任何待處理的事務都將被隱式回滾。如果autocommit
為True
或LEGACY_TRANSACTION_CONTROL
,則不執行隱式事務控制。請確保在關閉之前commit()
以避免丟失待處理的更改。
- execute(sql, parameters=(), /)¶
建立一個新的
Cursor
物件,並使用給定的 *sql* 和 *parameters* 在其上呼叫execute()
。返回新的遊標物件。
- executemany(sql, parameters, /)¶
建立一個新的
Cursor
物件,並使用給定的 *sql* 和 *parameters* 在其上呼叫executemany()
。返回新的遊標物件。
- executescript(sql_script, /)¶
建立一個新的
Cursor
物件,並使用給定的 *sql_script* 在其上呼叫executescript()
。返回新的遊標物件。
- create_function(name, narg, func, *, deterministic=False)¶
建立或刪除使用者定義的 SQL 函式。
- 引數:
3.8 版本中已更改: 添加了 deterministic 引數。
示例
>>> import hashlib >>> def md5sum(t): ... return hashlib.md5(t).hexdigest() >>> con = sqlite3.connect(":memory:") >>> con.create_function("md5", 1, md5sum) >>> for row in con.execute("SELECT md5(?)", (b"foo",)): ... print(row) ('acbd18db4cc2f85cedef654fccc4a4d8',) >>> con.close()
3.13 版本中已更改: 將 *name*、*narg* 和 *func* 作為關鍵字引數傳遞已棄用。這些引數將在 Python 3.15 中成為僅位置引數。
- create_aggregate(name, n_arg, aggregate_class)¶
建立或刪除使用者定義的 SQL 聚合函式。
- 引數:
name (字串) – SQL 聚合函式的名稱。
n_arg (整數) – SQL 聚合函式可以接受的引數數量。如果為
-1
,則它可以接受任意數量的引數。aggregate_class (類 | None) –
一個類必須實現以下方法
step()
: 向聚合中新增一行。finalize()
: 以 SQLite 原生支援的型別 返回聚合的最終結果。
step()
方法必須接受的引數數量由 *n_arg* 控制。設定為
None
以刪除現有 SQL 聚合函式。
示例
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.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]) con.close()
3.13 版本中已更改: 將 *name*、*n_arg* 和 *aggregate_class* 作為關鍵字引數傳遞已棄用。這些引數將在 Python 3.15 中成為僅位置引數。
- create_window_function(name, num_params, aggregate_class, /)¶
建立或刪除使用者定義的聚合視窗函式。
- 引數:
name (字串) – 要建立或刪除的 SQL 聚合視窗函式的名稱。
num_params (整數) – SQL 聚合視窗函式可以接受的引數數量。如果為
-1
,則它可以接受任意數量的引數。aggregate_class (類 | None) –
一個類必須實現以下方法
step()
: 向當前視窗新增一行。value()
: 返回聚合的當前值。inverse()
: 從當前視窗中刪除一行。finalize()
: 以 SQLite 原生支援的型別 返回聚合的最終結果。
step()
和value()
方法必須接受的引數數量由 *num_params* 控制。設定為
None
以刪除現有 SQL 聚合視窗函式。
- 引發:
NotSupportedError – 如果與早於 3.25.0 的 SQLite 版本一起使用,該版本不支援聚合視窗函式。
在 3.11 版本中新增。
示例
# Example taken from https://www.sqlite.org/windowfunctions.html#udfwinfunc class WindowSumInt: def __init__(self): self.count = 0 def step(self, value): """Add a row to the current window.""" self.count += value def value(self): """Return the current value of the aggregate.""" return self.count def inverse(self, value): """Remove a row from the current window.""" self.count -= value def finalize(self): """Return the final value of the aggregate. Any clean-up actions should be placed here. """ return self.count con = sqlite3.connect(":memory:") cur = con.execute("CREATE TABLE test(x, y)") values = [ ("a", 4), ("b", 5), ("c", 3), ("d", 8), ("e", 1), ] cur.executemany("INSERT INTO test VALUES(?, ?)", values) con.create_window_function("sumint", 1, WindowSumInt) cur.execute(""" SELECT x, sumint(y) OVER ( ORDER BY x ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) AS sum_y FROM test ORDER BY x """) print(cur.fetchall()) con.close()
- create_collation(name, callable, /)¶
使用排序函式 *callable* 建立名為 *name* 的排序規則。*callable* 將接收兩個
字串
引數,並且應返回一個整數
如果第一個排序高於第二個,則為
1
如果第一個排序低於第二個,則為
-1
如果它們排序相等,則為
0
以下示例顯示了一個反向排序的排序規則
def collate_reverse(string1, string2): if string1 == string2: return 0 elif string1 < string2: return 1 else: return -1 con = sqlite3.connect(":memory:") con.create_collation("reverse", collate_reverse) cur = con.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()
透過將 *callable* 設定為
None
來刪除排序函式。3.11 版本中已更改: 排序規則名稱可以包含任何 Unicode 字元。以前,只允許 ASCII 字元。
- interrupt()¶
從不同的執行緒呼叫此方法以中止可能正在連線上執行的任何查詢。中止的查詢將引發
OperationalError
。
- set_authorizer(authorizer_callback)¶
註冊 可呼叫物件 *authorizer_callback*,用於在每次嘗試訪問資料庫中表的列時呼叫。回撥應返回
SQLITE_OK
、SQLITE_DENY
或SQLITE_IGNORE
之一,以指示底層 SQLite 庫應如何處理對列的訪問。回撥的第一個引數表示要授權的操作型別。第二個和第三個引數將是引數或
None
,具體取決於第一個引數。第四個引數是資料庫的名稱("main"、"temp" 等)(如果適用)。第五個引數是負責訪問嘗試的最內層觸發器或檢視的名稱,如果此訪問嘗試直接來自輸入的 SQL 程式碼,則為None
。請查閱 SQLite 文件,瞭解第一個引數的可能值以及第二個和第三個引數的含義,具體取決於第一個引數。所有必要的常量都可以在
sqlite3
模組中找到。傳遞
None
作為 *authorizer_callback* 將停用授權器。3.11 版本中已更改: 添加了使用
None
停用授權器的支援。3.13 版本中已更改: 將 *authorizer_callback* 作為關鍵字引數傳遞已棄用。該引數將在 Python 3.15 中成為僅位置引數。
- set_progress_handler(progress_handler, n)¶
註冊 可呼叫物件 *progress_handler*,以便每 *n* 條 SQLite 虛擬機器指令都會呼叫它。這對於在長時間執行的操作期間從 SQLite 接收呼叫很有用,例如更新 GUI。
如果您想清除任何以前安裝的進度處理程式,請將 *progress_handler* 設定為
None
呼叫此方法。從處理程式函式返回非零值將終止當前正在執行的查詢,並導致它引發
DatabaseError
異常。3.13 版本中已更改: 將 *progress_handler* 作為關鍵字引數傳遞已棄用。該引數將在 Python 3.15 中成為僅位置引數。
- set_trace_callback(trace_callback)¶
註冊 可呼叫物件 *trace_callback*,以便為 SQLite 後端實際執行的每個 SQL 語句呼叫它。
傳遞給回撥的唯一引數是正在執行的語句(作為
str
)。回撥的返回值將被忽略。請注意,後端不僅執行傳遞給Cursor.execute()
方法的語句。其他來源包括sqlite3
模組的 事務管理 以及當前資料庫中定義的觸發器的執行。將
None
作為 *trace_callback* 傳遞將停用跟蹤回撥。備註
在跟蹤回撥中引發的異常不會傳播。作為開發和除錯輔助,請使用
enable_callback_tracebacks()
來啟用列印跟蹤回撥中引發的異常的回溯。在 3.3 版本加入。
3.13 版本中已更改: 將 *trace_callback* 作為關鍵字引數傳遞已棄用。該引數將在 Python 3.15 中成為僅位置引數。
- enable_load_extension(enabled, /)¶
如果 *enabled* 為
True
,則允許 SQLite 引擎從共享庫載入 SQLite 擴充套件;否則,禁止載入 SQLite 擴充套件。SQLite 擴充套件可以定義新函式、聚合或全新的虛擬表實現。一個著名的擴充套件是隨 SQLite 分發的全文搜尋擴充套件。備註
sqlite3
模組預設不構建為支援可載入擴充套件,因為某些平臺(特別是 macOS)的 SQLite 庫在編譯時未包含此功能。要獲得可載入擴充套件支援,您必須將--enable-loadable-sqlite-extensions
選項傳遞給 configure。引發一個 審計事件
sqlite3.enable_load_extension
,引數為connection
、enabled
。在 3.2 版本加入。
3.10 版本中已更改: 添加了
sqlite3.enable_load_extension
審計事件。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 loading 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, /, *, entrypoint=None)¶
從共享庫載入 SQLite 擴充套件。在呼叫此方法之前,使用
enable_load_extension()
啟用擴充套件載入。- 引數:
引發一個 審計事件
sqlite3.load_extension
,引數為connection
、path
。在 3.2 版本加入。
3.10 版本中已更改: 添加了
sqlite3.load_extension
審計事件。3.12 版本中已更改: 添加了 *entrypoint* 引數。
- iterdump(*, filter=None)¶
返回一個 迭代器,用於將資料庫轉儲為 SQL 原始碼。在儲存記憶體資料庫以便以後恢復時很有用。類似於 sqlite3 shell 中的
.dump
命令。- 引數:
filter (字串 | None) – 用於轉儲資料庫物件的可選
LIKE
模式,例如prefix_%
。如果為None
(預設值),則將包含所有資料庫物件。
示例
# Convert file example.db to SQL dump file dump.sql con = sqlite3.connect('example.db') with open('dump.sql', 'w') as f: for line in con.iterdump(): f.write('%s\n' % line) con.close()
3.13 版本中已更改: 添加了 *filter* 引數。
- backup(target, *, pages=-1, progress=None, name='main', sleep=0.250)¶
建立 SQLite 資料庫的備份。
即使資料庫被其他客戶端或同一連線同時訪問,也有效。
- 引數:
target (Connection) – 用於儲存備份的資料庫連線。
pages (整數) – 每次複製的頁數。如果等於或小於
0
,則整個資料庫將一次性複製。預設為-1
。progress (回撥函式 | None) – 如果設定為 可呼叫物件,則在每次備份迭代時呼叫它,並帶三個整數引數:上次迭代的 *status*、仍要複製的 *remaining* 頁數和 *total* 頁數。預設為
None
。name (字串) – 要備份的資料庫名稱。可以是
"main"
(預設)表示主資料庫,"temp"
表示臨時資料庫,或使用ATTACH DATABASE
SQL 語句附加的自定義資料庫名稱。sleep (浮點數) – 在連續嘗試備份剩餘頁面之間休眠的秒數。
示例 1,將現有資料庫複製到另一個數據庫
def progress(status, remaining, total): print(f'Copied {total-remaining} of {total} pages...') src = sqlite3.connect('example.db') dst = sqlite3.connect('backup.db') with dst: src.backup(dst, pages=1, progress=progress) dst.close() src.close()
示例 2,將現有資料庫複製到瞬時副本
src = sqlite3.connect('example.db') dst = sqlite3.connect(':memory:') src.backup(dst) dst.close() src.close()
在 3.7 版本加入。
- getlimit(category, /)¶
獲取連線執行時限制。
- 引數:
category (整數) – 要查詢的 SQLite 限制類別。
- 返回型別:
- 引發:
ProgrammingError – 如果底層 SQLite 庫無法識別 *category*。
例如,查詢
Connection
con
的 SQL 語句最大長度(預設為 1000000000)>>> con.getlimit(sqlite3.SQLITE_LIMIT_SQL_LENGTH) 1000000000
在 3.11 版本中新增。
- setlimit(category, limit, /)¶
設定連線執行時限制。嘗試將限制增加到其硬上限以上時,將靜默截斷為硬上限。無論限制是否更改,都返回限制的先前值。
- 引數:
category (整數) – 要設定的 SQLite 限制類別。
limit (整數) – 新限制的值。如果為負數,則當前限制不變。
- 返回型別:
- 引發:
ProgrammingError – 如果底層 SQLite 庫無法識別 *category*。
例如,將
Connection
con
的附加資料庫數量限制為 1(預設限制為 10)>>> con.setlimit(sqlite3.SQLITE_LIMIT_ATTACHED, 1) 10 >>> con.getlimit(sqlite3.SQLITE_LIMIT_ATTACHED) 1
在 3.11 版本中新增。
- getconfig(op, /)¶
查詢布林連線配置選項。
- 引數:
op (整數) – 一個 SQLITE_DBCONFIG 程式碼。
- 返回型別:
3.12 新版功能.
- setconfig(op, enable=True, /)¶
設定布林連線配置選項。
- 引數:
op (整數) – 一個 SQLITE_DBCONFIG 程式碼。
enable (布林值) – 如果應啟用配置選項,則為
True
(預設);如果應停用,則為False
。
3.12 新版功能.
- serialize(*, name='main')¶
將資料庫序列化為
bytes
物件。對於普通的磁碟資料庫檔案,序列化只是磁碟檔案的副本。對於記憶體資料庫或“臨時”資料庫,序列化是如果該資料庫被備份到磁碟時將寫入磁碟的相同位元組序列。備註
此方法僅在底層 SQLite 庫具有 serialize API 時可用。
在 3.11 版本中新增。
- deserialize(data, /, *, name='main')¶
將
serialized
資料庫反序列化到Connection
中。此方法會使資料庫連線從資料庫 name 斷開,然後根據 data 中包含的序列化將 name 作為記憶體資料庫重新開啟。- 引數:
- 引發:
OperationalError – 如果資料庫連線當前正在參與讀取事務或備份操作。
DatabaseError – 如果 data 不包含有效的 SQLite 資料庫。
OverflowError – 如果
len(data)
大於2**63 - 1
。
備註
此方法僅在底層 SQLite 庫具有 deserialize API 時可用。
在 3.11 版本中新增。
- autocommit¶
此屬性控制符合 PEP 249 的事務行為。
autocommit
有三個允許值False
:選擇符合 PEP 249 的事務行為,這意味著sqlite3
確保事務始終處於開啟狀態。使用commit()
和rollback()
關閉事務。這是
autocommit
的推薦值。True
:使用 SQLite 的 自動提交模式。commit()
和rollback()
在此模式下無效。LEGACY_TRANSACTION_CONTROL
:Python 3.12 之前(不符合 PEP 249)的事務控制。有關更多詳細資訊,請參閱isolation_level
。這目前是
autocommit
的預設值。
將
autocommit
更改為False
將開啟一個新事務,更改為True
將提交任何待處理的事務。有關更多詳細資訊,請參閱 透過 autocommit 屬性控制事務。
備註
除非
autocommit
設定為LEGACY_TRANSACTION_CONTROL
,否則isolation_level
屬性無效。3.12 新版功能.
- isolation_level¶
控制
sqlite3
的 舊式事務處理模式。如果設定為None
,則永遠不會隱式開啟事務。如果設定為"DEFERRED"
、"IMMEDIATE"
或"EXCLUSIVE"
之一,對應於底層 SQLite 事務行為,則執行 隱式事務管理。如果未被
connect()
的 isolation_level 引數覆蓋,則預設值為""
,它是"DEFERRED"
的別名。備註
建議使用
autocommit
控制事務處理,而不是使用isolation_level
。isolation_level
只有在autocommit
設定為LEGACY_TRANSACTION_CONTROL
(預設值)時才有效。
- row_factory¶
從此連線建立的
Cursor
物件的初始row_factory
。為此屬性賦值不會影響此連線現有遊標的row_factory
,僅影響新遊標。預設情況下為None
,這意味著每行作為tuple
返回。有關更多詳細資訊,請參閱 如何建立和使用行工廠。
- text_factory¶
一個 可呼叫物件,它接受一個
bytes
引數並返回其文字表示。對於資料型別為TEXT
的 SQLite 值,將呼叫此可呼叫物件。預設情況下,此屬性設定為str
。有關更多詳細資訊,請參閱 如何處理非 UTF-8 文字編碼。
- total_changes¶
返回自資料庫連線開啟以來已修改、插入或刪除的資料庫行總數。
遊標物件¶
Cursor
物件表示一個 資料庫遊標,用於執行 SQL 語句和管理獲取操作的上下文。遊標是使用Connection.cursor()
或使用任何 連線快捷方法 建立的。遊標物件是 迭代器,這意味著如果您
execute()
一個SELECT
查詢,您可以簡單地迭代遊標以獲取結果行for row in cur.execute("SELECT t FROM data"): print(row)
- class sqlite3.Cursor¶
Cursor
例項具有以下屬性和方法。- execute(sql, parameters=(), /)¶
執行單個 SQL 語句,可以選擇使用 佔位符 繫結 Python 值。
- 引數:
sql (str) – 單個 SQL 語句。
parameters (
dict
| sequence) – 要繫結到 sql 中佔位符的 Python 值。如果使用命名佔位符,則為dict
。如果使用未命名佔位符,則為 序列。請參閱 如何在 SQL 查詢中使用佔位符繫結值。
- 引發:
ProgrammingError – 當 sql 包含多個 SQL 語句時。當使用 命名佔位符 且 parameters 是序列而不是
dict
時。
如果
autocommit
是LEGACY_TRANSACTION_CONTROL
,isolation_level
不是None
,sql 是INSERT
、UPDATE
、DELETE
或REPLACE
語句,並且沒有開啟的事務,則在執行 sql 之前會隱式開啟一個事務。3.14 版本中已更改: 如果使用 命名佔位符 並且 parameters 是序列而不是
dict
,則會發出ProgrammingError
。使用
executescript()
執行多個 SQL 語句。
- executemany(sql, parameters, /)¶
對於 parameters 中的每個專案,重複執行 引數化 DML SQL 語句 sql。
使用與
execute()
相同的隱式事務處理。- 引數:
sql (str) – 單個 SQL DML 語句。
parameters (iterable) – 用於繫結 sql 中佔位符的引數的 可迭代物件。請參閱 如何在 SQL 查詢中使用佔位符繫結值。
- 引發:
ProgrammingError – 當 sql 包含多個 SQL 語句或不是 DML 語句時。當使用 命名佔位符 並且 parameters 中的專案是序列而不是
dict
時。
示例
rows = [ ("row1",), ("row2",), ] # cur is an sqlite3.Cursor object cur.executemany("INSERT INTO data VALUES(?)", rows)
備註
任何結果行都將被丟棄,包括帶有 RETURNING 子句 的 DML 語句。
3.14 版本中已更改: 如果使用 命名佔位符 並且 parameters 中的專案是序列而不是
dict
,則會發出ProgrammingError
。
- executescript(sql_script, /)¶
執行 sql_script 中的 SQL 語句。如果
autocommit
是LEGACY_TRANSACTION_CONTROL
並且存在待處理的事務,則首先執行隱式COMMIT
語句。不執行其他隱式事務控制;任何事務控制都必須新增到 sql_script 中。sql_script 必須是
string
。示例
# cur is an sqlite3.Cursor object cur.executescript(""" BEGIN; CREATE TABLE person(firstname, lastname, age); CREATE TABLE book(title, author, published); CREATE TABLE publisher(name, address); COMMIT; """)
- fetchone()¶
如果
row_factory
是None
,則將下一行查詢結果集作為tuple
返回。否則,將其傳遞給行工廠並返回其結果。如果沒有更多資料可用,則返回None
。
- fetchmany(size=cursor.arraysize)¶
將查詢結果的下一組行作為
list
返回。如果沒有更多行可用,則返回空列表。每次呼叫要獲取的行數由 size 引數指定。如果未給定 size,則
arraysize
確定要獲取的行數。如果可用的行數少於 size,則返回所有可用行。請注意,size 引數涉及效能考慮。為了獲得最佳效能,通常最好使用 arraysize 屬性。如果使用 size 引數,那麼最好在每次
fetchmany()
呼叫中保持相同的值。3.14.0(未釋出)版本中已更改: 負 size 值將被拒絕,並引發
ValueError
。
- close()¶
立即關閉遊標(而不是在呼叫
__del__
時)。從此時起,遊標將無法使用;如果嘗試對遊標執行任何操作,將引發
ProgrammingError
異常。
- setinputsizes(sizes, /)¶
DB-API 所必需。在
sqlite3
中不執行任何操作。
- setoutputsize(size, column=None, /)¶
DB-API 所必需。在
sqlite3
中不執行任何操作。
- arraysize¶
讀/寫屬性,控制
fetchmany()
返回的行數。預設值為 1,這意味著每次呼叫將獲取單行。3.14.0(未釋出)版本中已更改: 負值將被拒絕,並引發
ValueError
。
- connection¶
只讀屬性,提供屬於遊標的 SQLite 資料庫
Connection
。透過呼叫con.cursor()
建立的Cursor
物件將具有一個引用 con 的connection
屬性>>> con = sqlite3.connect(":memory:") >>> cur = con.cursor() >>> cur.connection == con True >>> con.close()
- description¶
只讀屬性,提供上次查詢的列名。為了與 Python DB API 相容,它為每列返回一個 7 元組,其中每個元組的最後六項為
None
。對於沒有匹配行的
SELECT
語句,它也會被設定。
- lastrowid¶
只讀屬性,提供最後插入行的行 ID。它僅在使用
execute()
方法成功執行INSERT
或REPLACE
語句後更新。對於其他語句,在executemany()
或executescript()
之後,或者如果插入失敗,lastrowid
的值保持不變。lastrowid
的初始值為None
。備註
對
WITHOUT ROWID
表的插入不記錄。3.6 版本中已更改: 增加了對
REPLACE
語句的支援。
- rowcount¶
只讀屬性,提供
INSERT
、UPDATE
、DELETE
和REPLACE
語句的修改行數;對於其他語句,包括 CTE 查詢,為-1
。它僅在語句執行完成後由execute()
和executemany()
方法更新。這意味著必須獲取任何結果行才能更新rowcount
。
- row_factory¶
控制從
Cursor
獲取的行如何表示。如果為None
,則行表示為tuple
。可以設定為包含的sqlite3.Row
;或者是一個 可呼叫物件,它接受兩個引數:一個Cursor
物件和行值tuple
,並返回一個表示 SQLite 行的自定義物件。預設值為建立
Cursor
時Connection.row_factory
的值。為此屬性賦值不會影響父連線的Connection.row_factory
。有關更多詳細資訊,請參閱 如何建立和使用行工廠。
行物件¶
- class sqlite3.Row¶
Row
例項作為Connection
物件的高度最佳化的row_factory
。它支援迭代、相等測試、len()
,以及透過列名和索引進行 對映 訪問。如果兩個
Row
物件具有相同的列名和值,則它們相等。有關更多詳細資訊,請參閱 如何建立和使用行工廠。
- keys()¶
返回一個
list
,其中包含作為strings
的列名。在查詢之後,它是Cursor.description
中每個元組的第一個成員。
3.5 版本中已更改: 增加了對切片的支援。
Blob 物件¶
- class sqlite3.Blob¶
在 3.11 版本中新增。
Blob
例項是一個 檔案類物件,可以讀寫 SQLite BLOB 中的資料。呼叫len(blob)
獲取 blob 的大小(位元組數)。使用索引和 切片 直接訪問 blob 資料。將
Blob
用作 上下文管理器 以確保在使用後關閉 blob 控制代碼。con = sqlite3.connect(":memory:") con.execute("CREATE TABLE test(blob_col blob)") con.execute("INSERT INTO test(blob_col) VALUES(zeroblob(13))") # Write to our blob, using two write operations: with con.blobopen("test", "blob_col", 1) as blob: blob.write(b"hello, ") blob.write(b"world.") # Modify the first and last bytes of our blob blob[0] = ord("H") blob[-1] = ord("!") # Read the contents of our blob with con.blobopen("test", "blob_col", 1) as blob: greeting = blob.read() print(greeting) # outputs "b'Hello, world!'" con.close()
- read(length=-1, /)¶
從 blob 的當前偏移位置讀取 length 位元組的資料。如果到達 blob 末尾,將返回到 EOF 的資料。當未指定 length 或為負數時,
read()
將一直讀取到 blob 的末尾。
- write(data, /)¶
在當前偏移量處將 data 寫入 blob。此函式不能更改 blob 長度。寫入超出 blob 末尾將引發
ValueError
。
- tell()¶
返回 blob 的當前訪問位置。
- seek(offset, origin=os.SEEK_SET, /)¶
將 blob 的當前訪問位置設定為 offset。origin 引數預設為
os.SEEK_SET
(絕對 blob 定位)。origin 的其他值為os.SEEK_CUR
(相對於當前位置查詢)和os.SEEK_END
(相對於 blob 末尾查詢)。
PrepareProtocol 物件¶
- class sqlite3.PrepareProtocol¶
PrepareProtocol 型別的唯一目的是作為 PEP 246 風格的適配協議,用於可以 自行適配 原生 SQLite 型別 的物件。
異常¶
異常層次結構由 DB-API 2.0(PEP 249)定義。
- exception sqlite3.Warning¶
此異常目前不會由
sqlite3
模組引發,但可能會由使用sqlite3
的應用程式引發,例如,如果使用者定義的函式在插入時截斷資料。Warning
是Exception
的子類。
- exception sqlite3.Error¶
此模組中其他異常的基類。使用此異常可在單個
except
語句中捕獲所有錯誤。Error
是Exception
的子類。如果異常源於 SQLite 庫內部,則以下兩個屬性將新增到異常中
- sqlite_errorcode¶
來自 SQLite API 的數字錯誤程式碼
在 3.11 版本中新增。
- sqlite_errorname¶
來自 SQLite API 的數字錯誤程式碼的符號名稱
在 3.11 版本中新增。
- exception sqlite3.InterfaceError¶
由於誤用低階 SQLite C API 而引發的異常。換句話說,如果引發此異常,則可能表示
sqlite3
模組中存在錯誤。InterfaceError
是Error
的子類。
- exception sqlite3.DatabaseError¶
由於與資料庫相關的錯誤而引發的異常。這作為幾種資料庫錯誤的基異常。它僅透過專門的子類隱式引發。
DatabaseError
是Error
的子類。
- exception sqlite3.DataError¶
由於處理資料的問題(例如數值超出範圍,字串過長)而引發的異常。
DataError
是DatabaseError
的子類。
- exception sqlite3.OperationalError¶
由於與資料庫操作相關的錯誤而引發的異常,不一定在程式設計師的控制之下。例如,找不到資料庫路徑,或者事務無法處理。
OperationalError
是DatabaseError
的子類。
- exception sqlite3.IntegrityError¶
當資料庫的參照完整性受到影響時(例如外部索引鍵檢查失敗)引發的異常。它是
DatabaseError
的子類。
- exception sqlite3.InternalError¶
當 SQLite 遇到內部錯誤時引發的異常。如果引發此異常,可能表示執行時 SQLite 庫存在問題。
InternalError
是DatabaseError
的子類。
- exception sqlite3.ProgrammingError¶
由於
sqlite3
API 程式設計錯誤而引發的異常,例如向查詢提供錯誤的繫結數量,或嘗試對已關閉的Connection
進行操作。ProgrammingError
是DatabaseError
的子類。
- exception sqlite3.NotSupportedError¶
當底層 SQLite 庫不支援某個方法或資料庫 API 時引發的異常。例如,如果底層 SQLite 庫不支援確定性函式,則在
create_function()
中將 deterministic 設定為True
。NotSupportedError
是DatabaseError
的子類。
SQLite 和 Python 型別¶
SQLite 原生支援以下型別:NULL
、INTEGER
、REAL
、TEXT
、BLOB
。
因此,以下 Python 型別可以毫無問題地傳送到 SQLite
Python 型別 |
SQLite 型別 |
---|---|
|
|
|
|
|
|
|
|
|
SQLite 型別預設轉換為 Python 型別的方式如下
SQLite 型別 |
Python 型別 |
---|---|
|
|
|
|
|
|
|
取決於 |
|
sqlite3
模組的型別系統可以透過兩種方式擴充套件:您可以透過 物件介面卡 在 SQLite 資料庫中儲存額外的 Python 型別,並且您可以透過 轉換器 讓 sqlite3
模組將 SQLite 型別轉換為 Python 型別。
預設介面卡和轉換器(已棄用)¶
備註
預設介面卡和轉換器自 Python 3.12 起已棄用。請改用 介面卡和轉換器示例 並根據您的需求進行調整。
已棄用的預設介面卡和轉換器包括
一個將
datetime.date
物件適配為 ISO 8601 格式的字串
的介面卡。一個將
datetime.datetime
物件適配為 ISO 8601 格式字串的介面卡。一個將 宣告的 “date” 型別轉換為
datetime.date
物件的轉換器。一個將宣告的“timestamp”型別轉換為
datetime.datetime
物件的轉換器。小數部分將被截斷為 6 位(微秒精度)。
備註
預設的“timestamp”轉換器會忽略資料庫中的 UTC 偏移量,並始終返回一個 naive 的 datetime.datetime
物件。要保留時間戳中的 UTC 偏移量,可以停用轉換器,或者使用 register_converter()
註冊一個支援偏移量的轉換器。
自 3.12 版本起已棄用。
命令列介面¶
sqlite3
模組可以作為指令碼呼叫,使用直譯器的 -m
開關,以提供一個簡單的 SQLite shell。引數簽名如下
python -m sqlite3 [-h] [-v] [filename] [sql]
輸入 .quit
或 CTRL-D 退出 shell。
- -h, --help¶
列印 CLI 幫助。
- -v, --version¶
列印底層 SQLite 庫版本。
3.12 新版功能.
操作指南¶
如何在 SQL 查詢中使用佔位符繫結值¶
SQL 操作通常需要使用 Python 變數中的值。但是,請注意使用 Python 的字串操作來組裝查詢,因為它們容易受到 SQL 注入攻擊。例如,攻擊者可以簡單地關閉單引號並注入 OR TRUE
來選擇所有行
>>> # Never do this -- insecure!
>>> symbol = input()
' OR TRUE; --
>>> sql = "SELECT * FROM stocks WHERE symbol = '%s'" % symbol
>>> print(sql)
SELECT * FROM stocks WHERE symbol = '' OR TRUE; --'
>>> cur.execute(sql)
相反,請使用 DB-API 的引數替換。要將變數插入查詢字串,請在字串中使用佔位符,並透過將實際值作為 tuple
傳遞給遊標的 execute()
方法的第二個引數,將其替換到查詢中。
SQL 語句可以使用兩種佔位符之一:問號(qmark 風格)或命名佔位符(命名風格)。對於 qmark 風格,parameters 必須是一個 序列,其長度必須與佔位符的數量匹配,否則會引發 ProgrammingError
。對於命名風格,parameters 必須是 dict
(或其子類)的例項,其中必須包含所有命名引數的鍵;任何多餘的專案都將被忽略。以下是兩種風格的示例
con = sqlite3.connect(":memory:")
cur = con.execute("CREATE TABLE lang(name, first_appeared)")
# This is the named style used with executemany():
data = (
{"name": "C", "year": 1972},
{"name": "Fortran", "year": 1957},
{"name": "Python", "year": 1991},
{"name": "Go", "year": 2009},
)
cur.executemany("INSERT INTO lang VALUES(:name, :year)", data)
# This is the qmark style used in a SELECT query:
params = (1972,)
cur.execute("SELECT * FROM lang WHERE first_appeared = ?", params)
print(cur.fetchall())
con.close()
備註
PEP 249 數字佔位符 不 受支援。如果使用,它們將被解釋為命名佔位符。
如何將自定義 Python 型別適配為 SQLite 值¶
SQLite 原生僅支援有限的資料型別集。要將自定義 Python 型別儲存在 SQLite 資料庫中,請將它們 適配 為 SQLite 原生理解的 Python 型別 之一。
有兩種方法可以將 Python 物件適配到 SQLite 型別:讓您的物件自行適配,或者使用 介面卡可呼叫物件。後者將優先於前者。對於匯出自定義型別的庫,啟用該型別自行適配可能是有意義的。作為應用程式開發人員,透過註冊自定義介面卡函式進行直接控制可能更有意義。
如何編寫可適配物件¶
假設我們有一個 Point
類,它表示笛卡爾座標系中的一對座標 x
和 y
。座標對將作為文字字串儲存在資料庫中,使用分號分隔座標。這可以透過新增一個 __conform__(self, protocol)
方法來實現,該方法返回適配的值。傳遞給 protocol 的物件將是 PrepareProtocol
型別。
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __conform__(self, protocol):
if protocol is sqlite3.PrepareProtocol:
return f"{self.x};{self.y}"
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("SELECT ?", (Point(4.0, -3.2),))
print(cur.fetchone()[0])
con.close()
如何註冊介面卡可呼叫物件¶
另一種可能性是建立一個將 Python 物件轉換為 SQLite 相容型別的函式。然後可以使用 register_adapter()
註冊此函式。
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def adapt_point(point):
return f"{point.x};{point.y}"
sqlite3.register_adapter(Point, adapt_point)
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("SELECT ?", (Point(1.0, 2.5),))
print(cur.fetchone()[0])
con.close()
如何將 SQLite 值轉換為自定義 Python 型別¶
編寫介面卡可讓您將自定義 Python 型別 轉換 為 SQLite 值。要將 SQLite 值 轉換 為自定義 Python 型別,我們使用 轉換器。
讓我們回到 Point
類。我們以分號分隔的方式將 x 和 y 座標作為字串儲存在 SQLite 中。
首先,我們將定義一個轉換器函式,該函式接受字串作為引數並從中構造一個 Point
物件。
備註
轉換器函式 總是 傳遞一個 bytes
物件,無論底層 SQLite 資料型別如何。
def convert_point(s):
x, y = map(float, s.split(b";"))
return Point(x, y)
我們現在需要告訴 sqlite3
何時應該轉換給定的 SQLite 值。這在連線到資料庫時完成,使用 connect()
的 detect_types 引數。有三個選項
隱式:將 detect_types 設定為
PARSE_DECLTYPES
顯式:將 detect_types 設定為
PARSE_COLNAMES
兩者:將 detect_types 設定為
sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES
。列名優先於宣告的型別。
以下示例說明了隱式和顯式方法
class Point:
def __init__(self, x, y):
self.x, self.y = x, y
def __repr__(self):
return f"Point({self.x}, {self.y})"
def adapt_point(point):
return f"{point.x};{point.y}"
def convert_point(s):
x, y = list(map(float, s.split(b";")))
return Point(x, y)
# Register the adapter and converter
sqlite3.register_adapter(Point, adapt_point)
sqlite3.register_converter("point", convert_point)
# 1) Parse using declared types
p = Point(4.0, -3.2)
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_DECLTYPES)
cur = con.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()
# 2) Parse using column names
con = sqlite3.connect(":memory:", detect_types=sqlite3.PARSE_COLNAMES)
cur = con.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()
介面卡和轉換器示例¶
本節展示了常見介面卡和轉換器的示例。
import datetime
import sqlite3
def adapt_date_iso(val):
"""Adapt datetime.date to ISO 8601 date."""
return val.isoformat()
def adapt_datetime_iso(val):
"""Adapt datetime.datetime to timezone-naive ISO 8601 date."""
return val.replace(tzinfo=None).isoformat()
def adapt_datetime_epoch(val):
"""Adapt datetime.datetime to Unix timestamp."""
return int(val.timestamp())
sqlite3.register_adapter(datetime.date, adapt_date_iso)
sqlite3.register_adapter(datetime.datetime, adapt_datetime_iso)
sqlite3.register_adapter(datetime.datetime, adapt_datetime_epoch)
def convert_date(val):
"""Convert ISO 8601 date to datetime.date object."""
return datetime.date.fromisoformat(val.decode())
def convert_datetime(val):
"""Convert ISO 8601 datetime to datetime.datetime object."""
return datetime.datetime.fromisoformat(val.decode())
def convert_timestamp(val):
"""Convert Unix epoch timestamp to datetime.datetime object."""
return datetime.datetime.fromtimestamp(int(val))
sqlite3.register_converter("date", convert_date)
sqlite3.register_converter("datetime", convert_datetime)
sqlite3.register_converter("timestamp", convert_timestamp)
如何使用連線快捷方法¶
透過使用 Connection
類的 execute()
、executemany()
和 executescript()
方法,您的程式碼可以寫得更簡潔,因為您不必顯式建立(通常是多餘的)Cursor
物件。相反,Cursor
物件會被隱式建立,並且這些快捷方法會返回遊標物件。這樣,您只需在 Connection
物件上進行一次呼叫,即可執行 SELECT
語句並直接遍歷它。
# Create and fill the table.
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE lang(name, first_appeared)")
data = [
("C++", 1985),
("Objective-C", 1984),
]
con.executemany("INSERT INTO lang(name, first_appeared) VALUES(?, ?)", data)
# Print the table contents
for row in con.execute("SELECT name, first_appeared FROM lang"):
print(row)
print("I just deleted", con.execute("DELETE FROM lang").rowcount, "rows")
# close() is not a shortcut method and it's not called automatically;
# the connection object should be closed manually
con.close()
如何使用連線上下文管理器¶
一個 Connection
物件可以用作上下文管理器,當離開上下文管理器的作用域時,它會自動提交或回滾未完成的事務。如果 with
語句的主體在沒有異常的情況下完成,則事務被提交。如果此提交失敗,或者 with
語句的主體引發了未捕獲的異常,則事務將回滾。如果 autocommit
為 False
,則在提交或回滾後會隱式開啟一個新事務。
如果在離開 with
語句的主體時沒有未完成的事務,或者如果 autocommit
為 True
,則上下文管理器不執行任何操作。
備註
上下文管理器既不隱式開啟新事務,也不關閉連線。如果您需要一個關閉連線的上下文管理器,請考慮使用 contextlib.closing()
。
con = sqlite3.connect(":memory:")
con.execute("CREATE TABLE lang(id INTEGER PRIMARY KEY, name VARCHAR UNIQUE)")
# Successful, con.commit() is called automatically afterwards
with con:
con.execute("INSERT INTO lang(name) VALUES(?)", ("Python",))
# 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 lang(name) VALUES(?)", ("Python",))
except sqlite3.IntegrityError:
print("couldn't add Python twice")
# Connection object used as context manager only commits or rollbacks transactions,
# so the connection object should be closed manually
con.close()
如何使用 SQLite URI¶
一些有用的 URI 技巧包括
以只讀模式開啟資料庫
>>> con = sqlite3.connect("file:tutorial.db?mode=ro", uri=True)
>>> con.execute("CREATE TABLE readonly(data)")
Traceback (most recent call last):
OperationalError: attempt to write a readonly database
>>> con.close()
如果資料庫檔案不存在,則不隱式建立新檔案;如果無法建立新檔案,將引發
OperationalError
>>> con = sqlite3.connect("file:nosuchdb.db?mode=rw", uri=True)
Traceback (most recent call last):
OperationalError: unable to open database file
建立一個共享的命名記憶體資料庫
db = "file:mem1?mode=memory&cache=shared"
con1 = sqlite3.connect(db, uri=True)
con2 = sqlite3.connect(db, uri=True)
with con1:
con1.execute("CREATE TABLE shared(data)")
con1.execute("INSERT INTO shared VALUES(28)")
res = con2.execute("SELECT data FROM shared")
assert res.fetchone() == (28,)
con1.close()
con2.close()
有關此功能的更多資訊,包括引數列表,可以在 SQLite URI 文件中找到。
如何建立和使用行工廠¶
預設情況下,sqlite3
將每一行表示為一個 tuple
。如果 tuple
不符合您的需求,您可以使用 sqlite3.Row
類或自定義的 row_factory
。
雖然 row_factory
作為屬性存在於 Cursor
和 Connection
上,但建議設定 Connection.row_factory
,以便從該連線建立的所有遊標都使用相同的行工廠。
Row
提供對列的索引和不區分大小寫的命名訪問,與 tuple
相比,記憶體開銷和效能影響極小。要將 Row
用作行工廠,請將其分配給 row_factory
屬性
>>> con = sqlite3.connect(":memory:")
>>> con.row_factory = sqlite3.Row
查詢現在返回 Row
物件
>>> res = con.execute("SELECT 'Earth' AS name, 6378 AS radius")
>>> row = res.fetchone()
>>> row.keys()
['name', 'radius']
>>> row[0] # Access by index.
'Earth'
>>> row["name"] # Access by name.
'Earth'
>>> row["RADIUS"] # Column names are case-insensitive.
6378
>>> con.close()
備註
在 SELECT
語句中可以省略 FROM
子句,如上例所示。在這種情況下,SQLite 返回一行,其中列由表示式(例如字面量)定義,並帶有給定的別名 expr AS alias
。
您可以建立一個自定義的 row_factory
,它將每一行作為 dict
返回,其中列名對映到值
def dict_factory(cursor, row):
fields = [column[0] for column in cursor.description]
return {key: value for key, value in zip(fields, row)}
使用它,查詢現在返回一個 dict
而不是一個 tuple
>>> con = sqlite3.connect(":memory:")
>>> con.row_factory = dict_factory
>>> for row in con.execute("SELECT 1 AS a, 2 AS b"):
... print(row)
{'a': 1, 'b': 2}
>>> con.close()
以下行工廠返回一個 命名元組
from collections import namedtuple
def namedtuple_factory(cursor, row):
fields = [column[0] for column in cursor.description]
cls = namedtuple("Row", fields)
return cls._make(row)
namedtuple_factory()
可以按如下方式使用
>>> con = sqlite3.connect(":memory:")
>>> con.row_factory = namedtuple_factory
>>> cur = con.execute("SELECT 1 AS a, 2 AS b")
>>> row = cur.fetchone()
>>> row
Row(a=1, b=2)
>>> row[0] # Indexed access.
1
>>> row.b # Attribute access.
2
>>> con.close()
經過一些調整,上述方法可以修改為使用 dataclass
或任何其他自定義類,而不是 namedtuple
。
如何處理非 UTF-8 文字編碼¶
預設情況下,sqlite3
使用 str
來適配資料型別為 TEXT
的 SQLite 值。這對於 UTF-8 編碼的文字工作良好,但對於其他編碼和無效的 UTF-8 可能會失敗。您可以使用自定義的 text_factory
來處理此類情況。
由於 SQLite 的 靈活型別,遇到包含非 UTF-8 編碼甚至任意資料的 TEXT
資料型別的表列並不少見。為了演示,假設我們有一個包含 ISO-8859-2 (Latin-2) 編碼文字的資料庫,例如一個捷克-英語詞典條目表。假設我們現在有一個連線到該資料庫的 Connection
例項 con
,我們可以使用此 text_factory
解碼 Latin-2 編碼的文字
con.text_factory = lambda data: str(data, encoding="latin2")
對於儲存在 TEXT
表列中的無效 UTF-8 或任意資料,您可以使用以下技術,借鑑自 Unicode HOWTO
con.text_factory = lambda data: str(data, errors="surrogateescape")
備註
sqlite3
模組 API 不支援包含代理字元的字串。
參見
說明¶
事務控制¶
sqlite3
提供了多種控制資料庫事務何時、如何開啟和關閉的方法。透過 autocommit 屬性進行事務控制 是推薦的方法,而 透過 isolation_level 屬性進行事務控制 保留了 Python 3.12 之前的行為。
透過 autocommit
屬性進行事務控制¶
控制事務行為的推薦方式是透過 Connection.autocommit
屬性,最好使用 connect()
的 autocommit 引數進行設定。
建議將 autocommit 設定為 False
,這意味著符合 PEP 249 規範的事務控制。這意味著
sqlite3
確保事務始終處於開啟狀態,因此connect()
、Connection.commit()
和Connection.rollback()
將隱式開啟一個新事務(後兩者在關閉掛起事務後立即開啟)。sqlite3
在開啟事務時使用BEGIN DEFERRED
語句。事務應使用
commit()
顯式提交。事務應使用
rollback()
顯式回滾。如果資料庫在存在掛起更改的情況下
close()
,將執行隱式回滾。
將 autocommit 設定為 True
以啟用 SQLite 的 自動提交模式。在此模式下,Connection.commit()
和 Connection.rollback()
無效。請注意,SQLite 的自動提交模式與符合 PEP 249 規範的 Connection.autocommit
屬性不同;使用 Connection.in_transaction
查詢底層 SQLite 自動提交模式。
將 autocommit 設定為 LEGACY_TRANSACTION_CONTROL
以將事務控制行為留給 Connection.isolation_level
屬性。有關更多資訊,請參閱 透過 isolation_level 屬性進行事務控制。
透過 isolation_level
屬性進行事務控制¶
備註
控制事務的推薦方式是透過 autocommit
屬性。請參閱 透過 autocommit 屬性進行事務控制。
如果 Connection.autocommit
設定為 LEGACY_TRANSACTION_CONTROL
(預設值),則事務行為由 Connection.isolation_level
屬性控制。否則,isolation_level
無效。
如果連線屬性 isolation_level
不是 None
,則在 execute()
和 executemany()
執行 INSERT
、UPDATE
、DELETE
或 REPLACE
語句之前會隱式開啟新事務;對於其他語句,不執行隱式事務處理。使用 commit()
和 rollback()
方法分別提交和回滾掛起事務。您可以透過 isolation_level
屬性選擇底層的 SQLite 事務行為 —— 即 sqlite3
是否以及隱式執行何種型別的 BEGIN
語句。
如果 isolation_level
設定為 None
,則根本不隱式開啟事務。這使得底層的 SQLite 庫處於 自動提交模式,但也允許使用者使用顯式 SQL 語句執行自己的事務處理。可以使用 in_transaction
屬性查詢底層的 SQLite 自動提交模式。
無論 isolation_level
的值如何,executescript()
方法在執行給定的 SQL 指令碼之前都會隱式提交任何掛起事務。
3.6 版本變更: sqlite3
過去會在 DDL 語句之前隱式提交一個未完成的事務。現在不再是這樣了。
3.12 版本變更: 現在推薦透過 autocommit
屬性來控制事務。