Client APIs
Querying
SQL queries can be sent to DuckDB using the `execute()` method of connections. Once a query has been executed, results can be retrieved using the `fetchone` and `fetchall` methods on the connection. `fetchall` will retrieve all results and complete the transaction. `fetchone` will retrieve a single row of results each time that it is invoked until no more results are available. The transaction will only close once `fetchone` is called and there are no more results remaining (the return value will be `None`). As an example, in the case of a query only returning a single row, `fetchone` should be called once to retrieve the results and a second time to close the transaction. Below are some short examples:  
```python
# 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
```  
The `description` property of the connection object contains the column names as per the standard.  
#### Prepared Statements {#docs:api:python:dbapi::prepared-statements}  
DuckDB also supports [prepared statements](#docs:sql:query_syntax:prepared_statements) in the API with the `execute` and `executemany` methods. The values may be passed as an additional parameter after a query that contains `?` or `$1` (dollar symbol and a number) placeholders. Using the `?` notation adds the values in the same sequence as passed within the Python parameter. Using the `$` notation allows for values to be reused within the SQL statement based on the number and index of the value found within the Python parameter. Values are converted according to the [conversion rules](#docs:api:python:conversion::object-conversion-python-object-to-duckdb).  
Here are some examples. First, insert a row using a [prepared statement](#docs:sql:query_syntax:prepared_statements):  
```python
con.execute("INSERT INTO items VALUES (?, ?, ?)", ["laptop", 2000, 1])
```  
Second, insert several rows using a [prepared statement](#docs:sql:query_syntax:prepared_statements):  
```python
con.executemany("INSERT INTO items VALUES (?, ?, ?)", [["chainsaw", 500, 10], ["iphone", 300, 2]] )
```  
Query the database using a [prepared statement](#docs:sql:query_syntax:prepared_statements):  
```python
con.execute("SELECT item FROM items WHERE value > ?", [400])
print(con.fetchall())
```  
```text
[('laptop',), ('chainsaw',)]
```  
Query using the `$` notation for a [prepared statement](#docs:sql:query_syntax:prepared_statements) and reused values:  
```python
con.execute("SELECT $1, $1, $2", ["duck", "goose"])
print(con.fetchall())
```  
```text
[('duck', 'duck', 'goose')]
```  
> **Warning.  ** Do *not* use `executemany` to insert large amounts of data into DuckDB. See the [data ingestion page](#docs:api:python:data_ingestion) for better options.