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

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

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

>>> cur.executemany('insert into user(name) values(?)', [('zhy',), ('Tom',), ('jane',)])

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

>>> cur.fetchmany(2)
[('a',), ('e',)]
>>> cur.fetchmany(2)
[('i',), ('o',)]
>>> cur.fetchmany(2)
[('u',)]

(6)fetchall()

获取查询结果的所有(剩余)行,返回列表。

例:

>>> cur.execute('select * from char')

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

>>> r = cur.fetchone()
>>> type(r)

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

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

>>> cur.execute("insert into point(addr, coordinate) values('Beijing', '35.5;120.0')")

>>> cur.execute("insert into point(addr, coordinate) values('NewYork', '-112.5;60.0')")


>>> cur.execute("select * from point").fetchall()
[(1, 'Beijing', '35.5;120.0'), (2, 'NewYork', '-112.5;60.0')]
>>> cur.execute("select * from point")

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

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

>>> today = datetime.date.today()
>>> now = datetime.datetime.now()

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

>>> cur.execute('SELECT * FROM test')

>>> row = cur.fetchone()
>>> print(today, '=>', row[0], type(row[0]))
2018-11-18 => 2018-11-18 
>>> print(now, '=>', row[1], type(row[1]))
2018-11-18 14:34:32.280495 => 2018-11-18 14:34:32.280495 

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

>>> row = cur.fetchone()
>>> print('current_date', row[0], type(row[0]))
current_date 2018-11-18 
>>> print('current_timestamp', row[1], type(row[1]))
current_timestamp 2018-11-18 06:38:40 

事务控制

底层 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)')

>>> con.executemany('INSERT INTO person VALUES(?,?)', persons)

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

(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() 方法,只有在不同的线程调用才有意义。

你可能感兴趣的:(Sqlite)