1. 程式人生 > >sqlite3 module

sqlite3 module

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

開啟一個 sqlite 資料庫檔案,返回 Connection 物件。

位置引數 database

指定資料庫檔案所在的路徑。可以使用“:memory:”在記憶體中開啟一個臨時的資料庫,但是資料不會被儲存帶磁碟中。

關鍵字引數 timeout

指定在丟擲異常前的等待時間,預設 ‘timeout=5’,單位秒。

引數 uri

True或False。當 uri=True,資料庫被解釋為一個 URI。這允許你指定一些查詢引數選項,比如以“只讀”模式開啟資料可,如下:

>>> conn = sqlite3.connect('file:/pyFile/sqliteDB/testDB.db?mode=ro', uri = True)
>>> cur=conn.cursor()
>>> cur.execute('select * from user').fetchall()
[(1, 'Tom', 24), (2, 'Michael', 25), (3, 'Jane', 18), (4, 'Tomax', 36)]
>>> conn.close()
常用的查詢引數
  • immutable=1

布林值,以“只讀”方式開啟的資料庫檔案,不能修改資料。

  • mode=ro

以“只讀”方式開啟的資料庫檔案,不能修改資料。

  • mode=rw

以“讀寫”方式開啟的資料庫檔案,可以修改資料。

  • mode=rwc

以“讀寫”方式開啟的資料庫檔案,可以修改資料。如果資料庫不存在則建立。

  • mode=memory

資料庫完全在記憶體中,不會和磁碟進行互動。

Connection Objects

(1)cursor(factory=Cursor)

獲取遊標。返回 Cursor 物件。

(2)commit()

This method commits the current transaction. If you don’t call this method, anything you did since the last call to commit() is not visible from other database connections. If you wonder why you don’t see the data you’ve written to the database, please check you didn’t forget to call this method.

(3)rollback()

This method rolls back any changes to the database since the last call to commit().

(4)close()

This closes the database connection. Note that this does not automatically call commit(). If you just close your database connection without calling commit() first, your changes will be lost!

(5)execute(sql[, parameters])

This is a nonstandard shortcut that creates a cursor object by calling the cursor() method, calls the cursor’s execute() method with the parameters given, and returns the cursor.

例:

>>> con = sqlite3.connect('/pyFile/sqliteDB/testDB.db')
>>> cur = con.cursor()
# 標準方法:使用Cursor物件
>>> cur.execute('select * from user').fetchall()
[(1, 'Allen', 24), (2, 'Michael', 25), (3, 'Jane', 18), (4, 'Tomax', 36)]
# 非標準方法:使用Connection物件
>>> con.execute('select * from user').fetchall()
[(1, 'Allen', 24), (2, 'Michael', 25), (3, 'Jane', 18), (4, 'Tomax', 36)]

(6)executemany(sql[, parameters])

This is a nonstandard shortcut that creates a cursor object by calling the cursor() method, calls the cursor’s executemany() method with the parameters given, and returns the cursor.

例:一次執行多條查詢語句

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

注意:引數為包含元組的列表。

(7)executescript(sql_script)

This is a nonstandard shortcut that creates a cursor object by calling the cursor() method, calls the cursor’s executescript() method with the given sql_script, and returns the cursor.

(8)create_function(name, num_params, func)

Creates a user-defined function that you can later use from within SQL statements under the function name name. num_params is the number of parameters the function accepts (if num_params is -1, the function may take any number of arguments), and func is a Python callable that is called as the SQL function.

例:查詢100年後的年齡

>>> cur.execute('select * from user').fetchall()
[(1, 'Allen', 24), (2, 'Michael', 25), (3, 'Jane', 18), (4, 'Tomax', 36)]

>>> def age_plus(t):
...     return t + 100
...
>>> con.create_function('ap', 1, age_plus)
>>> cur.execute('select name, ap(age) from user').fetchall()
[('Allen', 124), ('Michael', 125), ('Jane', 118), ('Tomax', 136)]

(9)interrupt()

You can call this method from a different thread to abort any queries that might be executing on the connection. The query will then abort and the caller will get an exception.

(10)text_factory

指定 sqlite 中的 TEXT 資料型別的返回型別,預設設定為 str,返回 Unicode 編碼的物件 。

con = sqlite3.connect('/pyFile/sqliteDB/testDB.db')
cur = con.cursor()
cur.execute('select * from user')
print(cur.fetchall())
C:\pyFile>python sqlite.py
[(1, 'Allen', 24), (2, 'Michael', 25), (3, 'Jane', 18), (4, 'Tomax', 36)]
# con.text_factory = bytes

C:\pyFile>python sqlite.py
[(1, b'Allen', 24), (2, b'Michael', 25), (3, b'Jane', 18), (4, b'Tomax', 36)]

# con.text_factory = lambda x : x.decode('utf-8') + 'foo'
C:\pyFile>python sqlite.py
[(1, 'Allenfoo', 24), (2, 'Michaelfoo', 25), (3, 'Janefoo', 18), (4, 'Tomaxfoo',
 36)]	

(11)total_changes

Returns the total number of database rows that have been modified, inserted, or deleted since the database connection was opened.

(12)iterdump()

Returns an iterator to dump the database in an SQL text format. Useful when saving an in-memory database for later restoration. This function provides the same capabilities as the .dump command in the sqlite3 shell.

例:

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

con = sqlite3.connect('existing_db.db')
with open('dump.sql', 'w') as f:
    for line in con.iterdump():
        f.write('%s\n' % line)

Cursor Objects

(1)execute(sql[, parameters])

執行一個 SQL 查詢語句。查詢語句可以帶引數, sqlite3 支援兩種佔位符:一是以“?”作為佔位符,二是“命名佔位符”。使用“?”佔位符時,引數為“?”對應的位置構成的元組。使用“命名佔位符”時,引數為對應名稱組成的字典。

例:

>>> import sqlite3
>>> con = sqlite3.connect('/pyFile/sqliteDB/testDB.db')
>>> cur = con.cursor()
>>> name = 'Judy'
>>> age = 30
# “?”佔位符:
>>> cur.execute('INSERT INTO user(name, age) VALUES(?, ?)', (name, age))
<sqlite3.Cursor object at 0x00000000024EEF10>
>>> cur.execute('SELECT * FROM user').fetchall()
[(1, 'Allen', 24), (2, 'Michael', 25), (3, 'Jane', 18), (4, 'Tomax', 36), (5, 'Judy', 30)]
# 命名佔位符:
>>> cur.execute('SELECT * FROM user WHERE name=:who AND age=:age', {'who': 'Judy
', 'age': 30})
<sqlite3.Cursor object at 0x00000000024EEEA0>
>>> cur.fetchone()
(5, 'Judy', 30)

注意:execute() 方法一次只會執行一條查詢語句,如果一次嘗試執行多條語句,會丟擲警告。可以使用 executescript() 方法一次執行多條語句。

(2)executemany(sql, seq_of_parameters)

對引數序列 seq_of_parameters 中的所有引數序列或對映執行SQL命令。sqlite3模組還允許使用迭代器產生引數而不是序列。引數 seq_of_parameters 必須是有元組構成的列表。

例:

>>> from sqlite3 import connect
>>> con = connect(':memory:')
>>> cur=con.cursor()
>>> cur.execute('create table user(ID integer, name text)')
<sqlite3.Cursor object at 0x000000000280EF10>
>>> cur.executemany('insert into user(name) values(?)', [('zhy',), ('Tom',), ('jane',)])
<sqlite3.Cursor object at 0x000000000280EF10>
>>> cur.execute('select * from user').fetchall()
[(None, 'zhy'), (None, 'Tom'), (None, 'jane')]

例:使用迭代器

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

(3)executescript(sql_script )

一次執行多個SQL語句。它首先發出一個COMMIT語句,然後執行它作為引數獲取的SQL指令碼。sql_script可以是一個 str 例項。

例:

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
    );
    """)

(4)fetchone()

獲取查詢結果集的下一行,返回單個序列。當沒有更多資料可用時,返回None。

(5)fetchmany(size=cursor.arraysize)

獲取查詢結果的下一組行,返回一個列表。當沒有更多行可用時,返回空列表。每一次呼叫獲取的行數可以通過引數指定。如果沒有指定,則預設每次返回 cursor.arraysize 行。

例:

>>> cur.execute('select * from char').fetchall()
[('a',), ('e',), ('i',), ('o',), ('u',)]

>>> cur.execute('select * from char').fetchmany(2)
[('a',), ('e',)]
>>> cur.execute('select * from char').fetchmany(2)
[('a',), ('e',)]

>>> cur.execute('select * from char')
<sqlite3.Cursor object at 0x000000000280EF10>
>>> cur.fetchmany(2)
[('a',), ('e',)]
>>> cur.fetchmany(2)
[('i',), ('o',)]
>>> cur.fetchmany(2)
[('u',)]

(6)fetchall()

獲取查詢結果的所有(剩餘)行,返回列表。

例:

>>> cur.execute('select * from char')
<sqlite3.Cursor object at 0x000000000280EF10>
>>> cur.fetchmany(3)
[('a',), ('e',), ('i',)]
>>> cur.fetchall()
[('o',), ('u',)]

注意:遊標的arraysize屬性可能會影響此操作的效能。

(7)close()

Close the cursor now (rather than whenever del is called).

(8)rowcount

(9)arraysize

Read/write attribute that controls the number of rows returned by fetchmany(). The default value is 1 which means a single row would be fetched per call.

(10)description

(11)connection

This read-only attribute provides the SQLite database Connection used by the Cursor object. A Cursor object created by calling con.cursor() will have a connection attribute that refers to con:

>>> con = sqlite3.connect(":memory:")
>>> cur = con.cursor()
>>> cur.connection == con
True

Row Objects

Row 例項作為一個高度優化的 row_factory 用於 Connection 物件。

(1)keys()

以列表形式返回查詢結果集的每一項的列名。

例:

>>> from sqlite3 import Row,connect
>>> con = connect('/pyFile/sqliteDB/testDB.db')
>>> con.row_factory = Row
>>> cur = con.cursor()
>>> cur.execute('SELECT * FROM user')
<sqlite3.Cursor object at 0x000000000281DF10>
>>> r = cur.fetchone()
>>> type(r)
<class 'sqlite3.Row'>
>>> tuple(r)
(1, 'Allen', 24)
>>> len(r)
3
>>> r[1]
'Allen'
>>> r[2]
24
>>> r.keys()
['ID', 'name', 'age']
>>> for member in r:
...     print(member)
...
1
Allen
24

例:

>>> cur.execute('select max(age) from user')
<sqlite3.Cursor object at 0x000000000281DF10>
>>> r = cur.fetchone()
>>> r.keys()
['max(age)']

Exceptions

SQLite and Python types

SQLite 原生支援以下幾種型別:NULL,INTEGER, REAL,TEXT,BLOB。
The following Python types can thus be sent to SQLite without any problem:

Python type SQLite type
None NULL
int INTEGER
float REAL
str TEXT
bytes BLOB

This is how SQLite types are converted to Python types by default:

SQLite type Python type
NULL None
INTEGER int
REAL float
TEXT depends on text_factory, str by default
BLOB bytes

使用介面卡在SQLite資料庫中儲存其他Python型別

SQLite本身僅支援一組有限的型別。要在SQLite中使用其他Python型別,必須使它們成為sqlite3 模組中支援的其中一種資料:one of NoneType, int, float, str, bytes。

有兩種方法:

(1)讓你的物件自己適應

如果自己編寫類,這是一個很好的方法。

例:假設你有一個座標類如下

class Point:
    def __init__(self, x, y):
        self.x, self.y = x, y

現在,您希望將該點座標儲存在單個 SQLite 列中。首先,必須先選擇一種支援的型別來表示該座標點。比如 str 型別,並用一個分號“;”分隔座標。然後需要給你的類定義一個方法 conform(self, protocol),該方法必須返回轉換後的值。引數 protocol 是 sqlite3.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;%f" % (self.x, self.y)	# 返回轉換後的字串

例:

>>> cur.execute('create table point(ID integer primary key autoincrement, addr text, coordinate text)')
<sqlite3.Cursor object at 0x000000000286DF10>
>>> cur.execute("insert into point(addr, coordinate) values('Beijing', '35.5;120.0')")
<sqlite3.Cursor object at 0x000000000286DF10>
>>> cur.execute("insert into point(addr, coordinate) values('NewYork', '-112.5;60.0')")
<sqlite3.Cursor object at 0x000000000286DF10>

>>> cur.execute("select * from point").fetchall()
[(1, 'Beijing', '35.5;120.0'), (2, 'NewYork', '-112.5;60.0')]
>>> cur.execute("select * from point")
<sqlite3.Cursor object at 0x000000000286DF10>
>>> cur.fetchone()[2]
'35.5;120.0'
(2)註冊可呼叫的介面卡

另一種方法是建立一個函式,將其他型別的資料轉換為用字串表示的型別,最後用register_adapter() 註冊該函式。
例:

>>> import sqlite3
>>> con = sqlite3.connect(':memory:')
>>> cur = con.cursor()
>>> class Point:
...     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)

>>> p = Point(56.0, -112.6)
>>> cur.execute('select ?', (p,))
<sqlite3.Cursor object at 0x000000000286DEA0>
>>> print(cur.fetchone()[0])
56.000000;-112.600000

sqlite3模組有兩個預設介面卡,用於Python的內建 datetime.date和datetime.datetime型別。現在讓我們假設我們想要儲存datetime.datetime不在ISO表示中的物件,而是儲存為Unix時間戳。
例:

import sqlite3
import datetime
import 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])
Converting SQLite values to custom Python types

編寫介面卡允許您將自定義Python型別傳送到 SQLite。但是為了使它真正有用,我們需要實現Python到SQLite再到Python的往返工作。

回到 Point 類。我們儲存了x和y座標,這些座標通過分號分隔作為SQLite中的字串。
首先,我們將定義一個轉換器函式,它接受字串作為引數並從中構造一個 Point 物件:

def convert_point(s):
    x, y = map(float, s.split(b";"))
    return Point(x, y)

注意:無論你傳送什麼型別的資料給 SQLite,轉換器函式始終攜帶一個 bytes 型別的物件被呼叫。

現在,您需要讓 sqlite3 模組知道您從資料庫中查詢的內容實際上是一個Point 型別的資料。有兩種方法可以做到這一點:

  • 通過隱含地宣告的型別
  • 通過明確地列名稱

兩種方式在 Module functions and constants 一節中描述,在常量條目 PARSE_DECLTYPES 和 PARSE_COLNAMES中。

例:

import sqlite3

class Point:
    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)).encode('ascii')

def convert_point(s):
    x, y = list(map(float, s.split(b";")))
    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()
Default adapters and converters

datetime模組中的 date 型別和 datetime 型別有預設介面卡。它們將作為ISO日期/ ISO時間戳傳送給SQLite。
datetime.date 被註冊為名稱 “date” 的預設轉換器,datetime.datetime 則被註冊為名稱 “timestamp” 。
這樣,在大多數情況下,您可以使用Python中的 date/timestamps,而無需任何額外的更改。

>>> import sqlite3, datetime
>>> con = sqlite3.connect(':memory:', detect_types = sqlite3.PARSE_DECLTYPES)
>>> cur = con.cursor()

>>> cur.execute('create table test(d date, ts timestamp)')
<sqlite3.Cursor object at 0x00000000025EDF10>
>>> today = datetime.date.today()
>>> now = datetime.datetime.now()

>>> cur.execute('insert into test(d, ts) values(?,?)',(today, now))
<sqlite3.Cursor object at 0x00000000025EDF10>
>>> cur.execute('SELECT * FROM test')
<sqlite3.Cursor object at 0x00000000025EDF10>
>>> row = cur.fetchone()
>>> print(today, '=>', row[0], type(row[0]))
2018-11-18 => 2018-11-18 <class 'datetime.date'>
>>> print(now, '=>', row[1], type(row[1]))
2018-11-18 14:34:32.280495 => 2018-11-18 14:34:32.280495 <class 'datetime.datetime'>

>>> cur.execute('SELECT current_date as "d [date]", current_timestamp as "ts [timestamp]"')
<sqlite3.Cursor object at 0x00000000025EDF10>
>>> row = cur.fetchone()
>>> print('current_date', row[0], type(row[0]))
current_date 2018-11-18 <class 'str'>
>>> print('current_timestamp', row[1], type(row[1]))
current_timestamp 2018-11-18 06:38:40 <class 'str'>

事務控制

底層 sqlite3 庫預設以 “autocommit” 模式執行,但Python中的 sqlite3 模組的預設方式不同。
“autocommit” 模式意味著修改資料庫的語句立刻生效。而一個“BEGIN”、“SAVEPOINT”語句使“autocommit” 模式失效。一個“COMMIT”、“ROLLBACK” 或 “RELEASE” 語句結束最外層事務,轉回 “autocommit” 模式。
Python的sqlite3 模組在執行一個Data Modification Language (DML)查詢(例如INSERT/UPDATE/DELETE/REPLACE)時會預設傳送一個“BEGIN” 語句。
可以通過 connect() 的 isolation_level 引數來控制隱式地呼叫哪種“BEGIN”語句,或者通過連線屬性 isolation_level。如果沒有指定 isolation_level 屬性,則一個單純的“BEGIN”語句會被使用,等同於指定 “DEFERRED”。其他可能的值為“IMMEDIATE”和“EXCLUSIVE”。
可以通過設定 isolation_level 為 None 來使sqlite3 模組原生的事務管理失效。這將使底層 sqlite3 庫以“autocommit”模式執行。然後,你可以通過明確地傳送 BEGIN,ROLLBACK, SAVEPOINT 和 RELEASE 語句來完全控制事務狀態。

有效地使用 sqlite3

(1)使用快捷方法

使用不標準的 Connection物件的 execute(),executemany()和executescript()方法可以使你的程式碼變得更加簡介,因為你不必去明確地生成 Cursor 物件(通常是不必要的)。Cursor 物件被隱式地生成且這些快捷方法返回 Cursor 物件。通過這種方式,你可以執行一個 SELECT 語句然後在Connection物件上直接通過單個的呼叫迭代它。

例:

>>> from sqlite3 import connect
>>> con = connect(':memory:')
>>> persons = [
...             ('Davis', 'Boss'),
...             ('Judy', 'Manager'),
...             ]
>>> con.execute('CREATE TABLE person(name, job)')
<sqlite3.Cursor object at 0x000000000283DF10>
>>> con.executemany('INSERT INTO person VALUES(?,?)', persons)
<sqlite3.Cursor object at 0x000000000283DEA0>
>>> for row in con.execute('SELECT * FROM person'):
...     print(row)
...
('Davis', 'Boss')
('Judy', 'Manager')
>>> print('I just deleted:', con.execute('DELETE FROM person').rowcount, ' rows')
I just deleted: 2  rows
>>> c = con.execute('select * from person')
>>> type(c)
<class 'sqlite3.Cursor'>

(2)通過名稱而不是索引訪問列

sqlite3 模組的一個有用功能是內建 sqlite3.Row類,旨在用作行工廠。用這個類包裝的行既可以通過索引(如元組)訪問,也可以通過名稱(不區分大小寫)訪問。

例:

>>> cur = con.execute('SELECT * FROM person')
>>> for row in cur:
...     print(row[0], row[1])
...
Davis Boss
Judy Manager
>>> for row in cur:
...     print(row['name'], row['job'])
...
>>> cur = con.execute('SELECT * FROM person')
>>> for row in cur:
...     print(row['name'], row['job'])
...
Davis Boss
Judy Manager

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

(3)使用連線(connection)作為上下文管理器

Connection 物件可以作為上下文管理器,它會自動提交或回滾事務。在有異常發生的事件中,它會回滾事務。否則它會提交事務。

例:

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

常見問題

多執行緒

舊版本的SQLite線上程之間共享連線存在問題。這就是Python模組不允許線上程之間共享連線和遊標的原因。如果您仍然嘗試這樣做,在執行時將會產生異常。
唯一的例外是呼叫 interrupt() 方法,只有在不同的執行緒呼叫才有意義。