Python DB API
Стандартный Python API для DuckDB предоставляет SQL-интерфейс, совместимый со спецификацией DB-API 2.0, описанной в PEP 249, аналогичный 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 в значение 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(). После закрытия последнего подключения к экземпляру базы данных, экземпляр базы данных также закрывается.
Запросы
SQL-запросы могут быть отправлены в DuckDB с помощью метода execute() подключений. После выполнения запроса результаты могут быть получены с помощью методов 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 объекта подключения содержит имена столбцов в соответствии со стандартом.
Предварительно скомпилированные запросы
DuckDB также поддерживает предварительно скомпилированные запросы в API с помощью методов execute и executemany. Значения могут быть переданы в качестве дополнительного параметра после запроса, содержащего ? или $1 (символ доллара и число) плейсхолдеры. Использование обозначения ? добавляет значения в той же последовательности, что и в параметрах Python. Использование обозначения $ позволяет повторно использовать значения в SQL-запросе на основе номера и индекса значения, найденного в параметре Python. Значения преобразуются в соответствии с правилами преобразования.
Вот несколько примеров. Во-первых, вставьте строку с помощью предварительно скомпилированного запроса:
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. При использовании параметров с именами вам необходимо предоставить словарь сопоставлений str к значению в аргументе parameters. Пример использования:
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])]
© Copyright 2018–2024 Stichting DuckDB Foundation
Licensed under the MIT License.
https://duckdb.org/docs/api/python/dbapi.html