⌘+k ctrl+k
1.1.3 (stable)
Search Shortcut cmd + k | ctrl + k
Python DB API

标准的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。一旦查询被执行,可以使用连接上的fetchonefetchall方法检索结果。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 中使用 executeexecutemany 方法的 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])]