标准的DuckDB Python API提供了一个符合PEP 249描述的DB-API 2.0规范的SQL接口,类似于SQLite Python API。
Connection
要使用该模块,您必须首先创建一个表示数据库连接的DuckDBPyConnection
对象。
这是通过duckdb.connect
方法完成的。
'config' 关键字参数可用于提供一个包含键值对的 dict
,这些键值对引用由 DuckDB 理解的 设置。
内存连接
特殊值 :memory:
可用于创建内存数据库。请注意,对于内存数据库,没有数据会持久化到磁盘(即,当你退出 Python 进程时,所有数据都会丢失)。
命名内存连接
特殊值 :memory:
也可以附加一个名称,例如::memory:conn3
。
当提供名称时,后续的 duckdb.connect
调用将创建到同一数据库的新连接,共享目录(视图、表、宏等)。
使用 :memory:
而不指定名称将始终创建一个新的、独立的数据库实例。
默认连接
默认情况下,我们创建一个(未命名的)内存数据库,它存在于duckdb
模块中。
DuckDBPyConnection
的每个方法也可以在duckdb
模块上使用,这些方法使用的就是这个连接。
特殊值 :default:
可用于获取此默认连接。
基于文件的连接
如果database
是一个文件路径,将建立一个到持久数据库的连接。
如果文件不存在,文件将被创建(文件的扩展名无关紧要,可以是.db
、.duckdb
或其他任何扩展名)。
read_only
连接
如果您希望以只读模式连接,可以将read_only
标志设置为True
。如果文件不存在,在只读模式下连接时不会创建该文件。
如果多个Python进程希望同时访问同一个数据库文件,则需要只读模式。
import duckdb
duckdb.execute("CREATE TABLE tbl AS SELECT 42 a")
con = duckdb.connect(":default:")
con.sql("SELECT * FROM tbl")
# or
duckdb.default_connection.sql("SELECT * FROM tbl")
┌───────┐
│ a │
│ int32 │
├───────┤
│ 42 │
└───────┘
import duckdb
# to start an in-memory database
con = duckdb.connect(database = ":memory:")
# to use a database file (not shared between processes)
con = duckdb.connect(database = "my-db.duckdb", read_only = False)
# to use a database file (shared between processes)
con = duckdb.connect(database = "my-db.duckdb", read_only = True)
# to explicitly get the default connection
con = duckdb.connect(database = ":default:")
如果你想为现有数据库创建第二个连接,可以使用cursor()
方法。例如,这可能有助于允许并行线程独立运行查询。单个连接是线程安全的,但在查询期间会被锁定,从而在这种情况下有效地序列化数据库访问。
当连接超出范围或使用close()
显式关闭时,连接会隐式关闭。一旦与数据库实例的最后一个连接关闭,数据库实例也会关闭。
Querying
SQL查询可以通过连接的execute()
方法发送到DuckDB。一旦查询被执行,可以使用连接上的fetchone
和fetchall
方法检索结果。fetchall
将检索所有结果并完成事务。fetchone
每次调用时将检索一行结果,直到没有更多结果可用。事务只有在fetchone
被调用且没有更多结果剩余时才会关闭(返回值将是None
)。例如,在查询只返回一行的情况下,应调用fetchone
一次以检索结果,第二次调用以关闭事务。以下是一些简短的示例:
# create a table
con.execute("CREATE TABLE items (item VARCHAR, value DECIMAL(10, 2), count INTEGER)")
# insert two items into the table
con.execute("INSERT INTO items VALUES ('jeans', 20.0, 1), ('hammer', 42.2, 2)")
# retrieve the items again
con.execute("SELECT * FROM items")
print(con.fetchall())
# [('jeans', Decimal('20.00'), 1), ('hammer', Decimal('42.20'), 2)]
# retrieve the items one at a time
con.execute("SELECT * FROM items")
print(con.fetchone())
# ('jeans', Decimal('20.00'), 1)
print(con.fetchone())
# ('hammer', Decimal('42.20'), 2)
print(con.fetchone()) # This closes the transaction. Any subsequent calls to .fetchone will return None
# None
连接对象的 description
属性包含根据标准的列名。
Prepared Statements
DuckDB 还支持在 API 中使用 execute
和 executemany
方法的 prepared statements。值可以作为包含 ?
或 $1
(美元符号和数字)占位符的查询后的附加参数传递。使用 ?
符号会按照 Python 参数中传递的顺序添加值。使用 $
符号允许根据 Python 参数中值的编号和索引在 SQL 语句中重复使用值。值根据 conversion rules 进行转换。
以下是一些示例。首先,使用预编译语句插入一行:
con.execute("INSERT INTO items VALUES (?, ?, ?)", ["laptop", 2000, 1])
其次,使用prepared statement插入几行数据:
con.executemany("INSERT INTO items VALUES (?, ?, ?)", [["chainsaw", 500, 10], ["iphone", 300, 2]] )
使用prepared statement查询数据库:
con.execute("SELECT item FROM items WHERE value > ?", [400])
print(con.fetchall())
[('laptop',), ('chainsaw',)]
使用$
符号进行查询,适用于预编译语句和重复使用的值:
con.execute("SELECT $1, $1, $2", ["duck", "goose"])
print(con.fetchall())
[('duck', 'duck', 'goose')]
警告 请不要使用
executemany
将大量数据插入到 DuckDB 中。请参阅 数据导入页面 以获取更好的选项。
命名参数
除了标准的未命名参数,如$1
、$2
等,还可以提供命名参数,如$my_parameter
。
使用命名参数时,您需要在parameters
参数中提供一个str
到值的字典映射。
以下是一个使用示例:
import duckdb
res = duckdb.execute("""
SELECT
$my_param,
$other_param,
$also_param
""",
{
"my_param": 5,
"other_param": "DuckDB",
"also_param": [42]
}
).fetchall()
print(res)
[(5, 'DuckDB', [42])]