快速入门#
您好,欢迎来到十二分钟快速入门教程。
连接到数据库#
首先,您需要导入 dataset 包 :)
import dataset
要连接到数据库,您需要通过其 URL 来识别它,它基本上是一个字符串,格式为 "dialect://user:password@host/dbname"
。以下是一些针对不同数据库后端的示例
# connecting to a SQLite database
db = dataset.connect('sqlite:///mydatabase.db')
# connecting to a MySQL database with user and password
db = dataset.connect('mysql://user:password@localhost/mydatabase')
# connecting to a PostgreSQL database
db = dataset.connect('postgresql://scott:tiger@localhost:5432/mydatabase')
也可以将 URL 定义为名为 DATABASE_URL 的环境变量,这样您就可以在没有显式传递 URL 的情况下初始化数据库连接。
db = dataset.connect()
根据您使用的数据库,您可能还需要安装数据库绑定以支持该数据库。SQLite 包含在 Python 核心库中,但 PostgreSQL 需要安装 psycopg2
。MySQL 可以通过安装 mysql-db
驱动程序来启用。
存储数据#
要存储一些数据,您需要获取对表的引用。您无需担心表是否已存在,因为 dataset 会自动创建它。
# get a reference to the table 'user'
table = db['user']
现在,将数据存储到表中只需一个函数调用。只需将一个 dict 传递给 insert。请注意,您无需创建 name 和 age 列 - dataset 会自动完成此操作。
# Insert a new record.
table.insert(dict(name='John Doe', age=46, country='China'))
# dataset will create "missing" columns any time you insert a dict with an unknown key
table.insert(dict(name='Jane Doe', age=37, country='France', gender='female'))
更新现有条目也很容易。
table.update(dict(name='John Doe', age=47), ['name'])
作为第二个参数给出的过滤器列列表使用第一列中的值进行过滤。如果您不想更新特定值,只需使用自动生成的 id
列。
使用事务#
您可以将一组数据库更新分组到一个事务中。在这种情况下,所有更新将一次性提交,或者在出现异常时,所有更新都将回滚。事务通过上下文管理器支持,因此可以通过 with
语句使用。
with dataset.connect() as tx:
tx['user'].insert(dict(name='John Doe', age=46, country='China'))
您可以通过显式调用方法 begin()
、commit()
和 rollback()
来获得相同的功能。
db = dataset.connect()
db.begin()
try:
db['user'].insert(dict(name='John Doe', age=46, country='China'))
db.commit()
except:
db.rollback()
嵌套事务也受支持。
db = dataset.connect()
with db as tx1:
tx1['user'].insert(dict(name='John Doe', age=46, country='China'))
with db as tx2:
tx2['user'].insert(dict(name='Jane Doe', age=37, country='France', gender='female'))
检查数据库和表#
在处理未知数据库时,我们可能希望首先检查其结构。为了开始探索,让我们找出存储在数据库中的表。
>>> print(db.tables)
[u'user']
现在,让我们列出表 user
中可用的所有列。
>>> print(db['user'].columns)
[u'id', u'country', u'age', u'name', u'gender']
使用 len()
,我们可以获取表中的总行数。
>>> print(len(db['user']))
2
从表中读取数据#
现在让我们从表中获取一些真实数据。
users = db['user'].all()
如果我们只想遍历表中的所有行,我们可以省略 all()
for user in db['user']:
print(user['age'])
我们可以使用 find()
和 find_one()
搜索特定条目。
# All users from China
chinese_users = table.find(country='China')
# Get a specific user
john = table.find_one(name='John Doe')
# Find multiple at once
winners = table.find(id=[1, 3, 7])
# Find by comparison operator
elderly_users = table.find(age={'>=': 70})
possible_customers = table.find(age={'between': [21, 80]})
# Use the underlying SQLAlchemy directly
elderly_users = table.find(table.table.columns.age >= 70)
有关复杂过滤器的详细信息,请参阅 高级过滤器。
使用 distinct()
,我们可以获取在一列或多列中具有唯一值的行的集合。
# Get one user per country
db['user'].distinct('country')
最后,您可以使用 row_type
参数来选择结果将以哪种数据类型返回。
import dataset
from stuf import stuf
db = dataset.connect('sqlite:///mydatabase.db', row_type=stuf)
现在,内容将以 stuf
对象返回(基本上,dict
对象,其元素可以通过属性 (item.name
) 和索引 (item['name']
) 访问)。
运行自定义 SQL 查询#
当然,您使用数据库的主要原因是您希望使用 SQL 查询的全部功能。以下是如何使用 dataset
运行它们。
result = db.query('SELECT country, COUNT(*) c FROM user GROUP BY country')
for row in result:
print(row['country'], row['c'])
query()
方法也可以用于访问底层的 SQLAlchemy 核心 API,它允许以编程方式构建更复杂的查询。
table = db['user'].table
statement = table.select(table.c.name.like('%John%'))
result = db.query(statement)
dataset 的局限性#
dataset
的目标是通过以 Pythonic 方式表达一些相对基本的运算来简化基本的数据库操作。这种方法的缺点是,随着应用程序变得越来越复杂,您可能需要访问更高级的操作,并被迫切换到使用 SQLAlchemy 本身,而没有 dataset 层(相反,您可能希望使用 SQLAlchemy 的 ORM)。
当那一刻到来时,接受它。SQLAlchemy 是一段很棒的 Python 代码,它将为您提供对所有 SQL 函数的惯用访问。
一些在 dataset
中未公开的 SQL 特定方面,并且被认为超出项目范围,包括
表之间的外键关系,以及以惯用 Python 方式表达一对多和多对多关系。
Python 封装的
JOIN
查询。创建数据库或管理 DBMS 软件。
支持 Python 2.x
还有一些功能可能在将来支持起来很酷,但这需要大量的工程工作。
异步操作
数据库本地的
UPSERT
语义