⌘+k ctrl+k
1.3 (稳定版)
搜索快捷键 cmd + k | ctrl + k
Python DB API

标准的 DuckDB Python API 提供了一个符合 PEP 249 中描述的 DB-API 2.0 规范 的 SQL 接口,类似于 SQLite Python API

连接

要使用此模块,您必须首先创建一个代表数据库连接的 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() 显式关闭时会自动关闭。一旦与数据库实例的最后一个连接关闭,该数据库实例也会关闭。

查询

可以使用连接的 execute() 方法将 SQL 查询发送到 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 属性包含符合标准的列名。

预处理语句

DuckDB 还支持使用 executeexecutemany 方法在 API 中使用预处理语句。值可以作为附加参数传递,位于包含 ?$1(美元符号和数字)占位符的查询之后。使用 ? 符号会按照 Python 参数中传递的相同顺序添加值。使用 $ 符号允许根据 Python 参数中找到的值的数量和索引在 SQL 语句中重复使用值。值会根据转换规则进行转换。

以下是一些示例。首先,使用预处理语句插入一行

con.execute("INSERT INTO items VALUES (?, ?, ?)", ["laptop", 2000, 1])

其次,使用预处理语句插入多行

con.executemany("INSERT INTO items VALUES (?, ?, ?)", [["chainsaw", 500, 10], ["iphone", 300, 2]] )

使用预处理语句查询数据库

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