Search Shortcut cmd + k | ctrl + k

- Installation
- Documentation

- Getting Started
- Connect

- Overview
- Concurrency

- Data Import

- Overview
- Data Sources
- CSV Files

- Overview
- Auto Detection
- Reading Faulty CSV Files
- Tips

- JSON Files

- Overview
- Creating JSON
- Loading JSON
- Writing JSON
- JSON Type
- JSON Functions
- Format Settings
- Installing and Loading
- SQL to / from JSON
- Caveats

- Multiple Files

- Overview
- Combining Schemas

- Parquet Files

- Overview
- Metadata
- Encryption
- Tips

- Partitioning

- Hive Partitioning
- Partitioned Writes

- Appender
- INSERT Statements

- Client APIs

- Overview
- C

- Overview
- Startup
- Configuration
- Query
- Data Chunks
- Vectors
- Values
- Types
- Prepared Statements
- Appender
- Table Functions
- Replacement Scans
- API Reference

- C++
- CLI

- Overview
- Arguments
- Dot Commands
- Output Formats
- Editing
- Autocomplete
- Syntax Highlighting

- Dart
- Go
- Java
- Julia
- Node.js (Neo)

- Overview

- Node.js

- Overview
- API Reference

- Python

- Overview
- Data Ingestion
- Conversion between DuckDB and Python
- DB API
- Relational API
- Function API
- Types API
- Expression API
- Spark API
- API Reference
- Known Python Issues

- R
- Rust
- Swift
- Wasm

- Overview
- Instantiation
- Data Ingestion
- Query
- Extensions

- ADBC
- ODBC

- Overview
- Linux Setup
- Windows Setup
- macOS Setup
- Configuration

- SQL

- Introduction
- Statements

- Overview
- ANALYZE
- ALTER TABLE
- ALTER VIEW
- ATTACH and DETACH
- CALL
- CHECKPOINT
- COMMENT ON
- COPY
- CREATE INDEX
- CREATE MACRO
- CREATE SCHEMA
- CREATE SECRET
- CREATE SEQUENCE
- CREATE TABLE
- CREATE VIEW
- CREATE TYPE
- DELETE
- DESCRIBE
- DROP
- EXPORT and IMPORT DATABASE
- INSERT
- LOAD / INSTALL
- PIVOT
- Profiling
- SELECT
- SET / RESET
- SET VARIABLE
- SUMMARIZE
- Transaction Management
- UNPIVOT
- UPDATE
- USE
- VACUUM

- Query Syntax

- SELECT
- FROM and JOIN
- WHERE
- GROUP BY
- GROUPING SETS
- HAVING
- ORDER BY
- LIMIT and OFFSET
- SAMPLE
- Unnesting
- WITH
- WINDOW
- QUALIFY
- VALUES
- FILTER
- Set Operations
- Prepared Statements

- Data Types

- Overview
- Array
- Bitstring
- Blob
- Boolean
- Date
- Enum
- Interval
- List
- Literal Types
- Map
- NULL Values
- Numeric
- Struct
- Text
- Time
- Timestamp
- Time Zones
- Union
- Typecasting

- Expressions

- Overview
- CASE Statement
- Casting
- Collations
- Comparisons
- IN Operator
- Logical Operators
- Star Expression
- Subqueries

- Functions

- Overview
- Aggregate Functions
- Array Functions
- Bitstring Functions
- Blob Functions
- Date Format Functions
- Date Functions
- Date Part Functions
- Enum Functions
- Interval Functions
- Lambda Functions
- List Functions
- Map Functions
- Nested Functions
- Numeric Functions
- Pattern Matching
- Regular Expressions
- Struct Functions
- Text Functions
- Time Functions
- Timestamp Functions
- Timestamp with Time Zone Functions
- Union Functions
- Utility Functions
- Window Functions

- Constraints
- Indexes
- Meta Queries

- Information Schema
- Metadata Functions

- DuckDB's SQL Dialect

- Overview
- Indexing
- Friendly SQL
- Keywords and Identifiers
- Order Preservation
- PostgreSQL Compatibility

- Samples

- Configuration

- Overview
- Pragmas
- Secrets Manager

- Extensions

- Overview
- Core Extensions
- Community Extensions
- Working with Extensions
- Versioning of Extensions
- Arrow
- AutoComplete
- AWS
- Azure
- Delta
- Excel
- Full Text Search
- httpfs (HTTP and S3)

- Overview
- HTTP(S) Support
- Hugging Face
- S3 API Support
- Legacy Authentication Scheme for S3 API

- Iceberg
- ICU
- inet
- jemalloc
- MySQL
- PostgreSQL
- Spatial

- Overview
- Function Reference
- R-Tree Indexes
- GDAL Integration

- SQLite
- Substrait
- TPC-DS
- TPC-H
- VSS

- Guides

- Overview
- Data Viewers

- Tableau
- CLI Charting with YouPlot

- Database Integration

- Overview
- MySQL Import
- PostgreSQL Import
- SQLite Import

- File Formats

- Overview
- CSV Import
- CSV Export
- Directly Reading Files
- Excel Import
- Excel Export
- JSON Import
- JSON Export
- Parquet Import
- Parquet Export
- Querying Parquet Files

- Network and Cloud Storage

- Overview
- HTTP Parquet Import
- S3 Parquet Import
- S3 Parquet Export
- S3 Iceberg Import
- S3 Express One
- GCS Import
- Cloudflare R2 Import
- DuckDB over HTTPS / S3

- Meta Queries

- Describe Table
- EXPLAIN: Inspect Query Plans
- EXPLAIN ANALYZE: Profile Queries
- List Tables
- Summarize
- DuckDB Environment

- ODBC

- ODBC Guide

- Performance

- Overview
- Environment
- Import
- Schema
- Indexing
- Join Operations
- File Formats
- How to Tune Workloads
- My Workload Is Slow
- Benchmarks

- Python

- Installation
- Executing SQL
- Jupyter Notebooks
- SQL on Pandas
- Import from Pandas
- Export to Pandas
- Import from Numpy
- Export to Numpy
- SQL on Arrow
- Import from Arrow
- Export to Arrow
- Relational API on Pandas
- Multiple Python Threads
- Integration with Ibis
- Integration with Polars
- Using fsspec Filesystems

- SQL Editors

- DBeaver SQL IDE

- SQL Features

- AsOf Join
- Full-Text Search
- query and query_table Functions

- Snippets

- Create Synthetic Data
- Sharing Macros

- Glossary of Terms
- Browse Offline

- Operations Manual

- Overview
- Limits
- Non-Deterministic Behavior
- Embedding DuckDB
- DuckDB's Footprint

- Files Created by DuckDB
- Gitignore for DuckDB
- Reclaiming Space

- Securing DuckDB

- Overview
- Securing Extensions

- Development

- DuckDB Repositories
- Testing

- Overview
- sqllogictest Introduction
- Writing Tests
- Debugging
- Result Verification
- Persistent Testing
- Loops
- Multiple Connections
- Catch

- Profiling
- Release Calendar
- Building

- Overview
- Build Instructions
- Build Configuration
- Building Extensions
- Platforms
- Troubleshooting

- Benchmark Suite

- Internals

- Overview
- Storage Versions and Format
- Execution Format
- Pivot

- Sitemap
- Why DuckDB
- Media
- FAQ
- Code of Conduct
- Live Demo

Appender

Appenders are the most efficient way of loading data into DuckDB from within the C interface, and are recommended for fast data loading. The appender is much faster than using prepared statements or individual `INSERT INTO` statements.

Appends are made in row-wise format. For every column, a `duckdb_append_[type]` call should be made, after which the row should be finished by calling `duckdb_appender_end_row`. After all rows have been appended, `duckdb_appender_destroy` should be used to finalize the appender and clean up the resulting memory.

Note that `duckdb_appender_destroy` should always be called on the resulting appender, even if the function returns `DuckDBError`.

## Example

    duckdb_query(con, "CREATE TABLE people (id INTEGER, name VARCHAR)", NULL);

    duckdb_appender appender;
    if (duckdb_appender_create(con, NULL, "people", &appender) == DuckDBError) {
      // handle error
    }
    // append the first row (1, Mark)
    duckdb_append_int32(appender, 1);
    duckdb_append_varchar(appender, "Mark");
    duckdb_appender_end_row(appender);

    // append the second row (2, Hannes)
    duckdb_append_int32(appender, 2);
    duckdb_append_varchar(appender, "Hannes");
    duckdb_appender_end_row(appender);

    // finish appending and flush all the rows to the table
    duckdb_appender_destroy(&appender);

## API Reference Overview

    duckdb_state duckdb_appender_create(duckdb_connection connection, const char *schema, const char *table, duckdb_appender *out_appender);
    idx_t duckdb_appender_column_count(duckdb_appender appender);
    duckdb_logical_type duckdb_appender_column_type(duckdb_appender appender, idx_t col_idx);
    const char *duckdb_appender_error(duckdb_appender appender);
    duckdb_state duckdb_appender_flush(duckdb_appender appender);
    duckdb_state duckdb_appender_close(duckdb_appender appender);
    duckdb_state duckdb_appender_destroy(duckdb_appender *appender);
    duckdb_state duckdb_appender_begin_row(duckdb_appender appender);
    duckdb_state duckdb_appender_end_row(duckdb_appender appender);
    duckdb_state duckdb_append_default(duckdb_appender appender);
    duckdb_state duckdb_append_bool(duckdb_appender appender, bool value);
    duckdb_state duckdb_append_int8(duckdb_appender appender, int8_t value);
    duckdb_state duckdb_append_int16(duckdb_appender appender, int16_t value);
    duckdb_state duckdb_append_int32(duckdb_appender appender, int32_t value);
    duckdb_state duckdb_append_int64(duckdb_appender appender, int64_t value);
    duckdb_state duckdb_append_hugeint(duckdb_appender appender, duckdb_hugeint value);
    duckdb_state duckdb_append_uint8(duckdb_appender appender, uint8_t value);
    duckdb_state duckdb_append_uint16(duckdb_appender appender, uint16_t value);
    duckdb_state duckdb_append_uint32(duckdb_appender appender, uint32_t value);
    duckdb_state duckdb_append_uint64(duckdb_appender appender, uint64_t value);
    duckdb_state duckdb_append_uhugeint(duckdb_appender appender, duckdb_uhugeint value);
    duckdb_state duckdb_append_float(duckdb_appender appender, float value);
    duckdb_state duckdb_append_double(duckdb_appender appender, double value);
    duckdb_state duckdb_append_date(duckdb_appender appender, duckdb_date value);
    duckdb_state duckdb_append_time(duckdb_appender appender, duckdb_time value);
    duckdb_state duckdb_append_timestamp(duckdb_appender appender, duckdb_timestamp value);
    duckdb_state duckdb_append_interval(duckdb_appender appender, duckdb_interval value);
    duckdb_state duckdb_append_varchar(duckdb_appender appender, const char *val);
    duckdb_state duckdb_append_varchar_length(duckdb_appender appender, const char *val, idx_t length);
    duckdb_state duckdb_append_blob(duckdb_appender appender, const void *data, idx_t length);
    duckdb_state duckdb_append_null(duckdb_appender appender);
    duckdb_state duckdb_append_data_chunk(duckdb_appender appender, duckdb_data_chunk chunk);

#### `duckdb_appender_create`

Creates an appender object.

Note that the object must be destroyed with `duckdb_appender_destroy`.

##### Syntax

    duckdb_state duckdb_appender_create(
      duckdb_connection connection,
      const char *schema,
      const char *table,
      duckdb_appender *out_appender
    );

##### Parameters

- `connection`: The connection context to create the appender in.
- `schema`: The schema of the table to append to, or `nullptr` for the default schema.
- `table`: The table name to append to.
- `out_appender`: The resulting appender object.

##### Return Value

`DuckDBSuccess` on success or `DuckDBError` on failure.

#### `duckdb_appender_column_count`

Returns the number of columns in the table that belongs to the appender.

##### Syntax

    idx_t duckdb_appender_column_count(
      duckdb_appender appender
    );

##### Parameters

- `appender`: The appender to get the column count from.

##### Return Value

The number of columns in the table.

#### `duckdb_appender_column_type`

Returns the type of the column at the specified index.

Note: The resulting type should be destroyed with `duckdb_destroy_logical_type`.

##### Syntax

    duckdb_logical_type duckdb_appender_column_type(
      duckdb_appender appender,
      idx_t col_idx
    );

##### Parameters

- `appender`: The appender to get the column type from.
- `col_idx`: The index of the column to get the type of.

##### Return Value

The duckdb_logical_type of the column.

#### `duckdb_appender_error`

Returns the error message associated with the given appender. If the appender has no error message, this returns `nullptr` instead.

The error message should not be freed. It will be de-allocated when `duckdb_appender_destroy` is called.

##### Syntax

    const char *duckdb_appender_error(
      duckdb_appender appender
    );

##### Parameters

- `appender`: The appender to get the error from.

##### Return Value

The error message, or `nullptr` if there is none.

#### `duckdb_appender_flush`

Flush the appender to the table, forcing the cache of the appender to be cleared. If flushing the data triggers a constraint violation or any other error, then all data is invalidated, and this function returns DuckDBError. It is not possible to append more values. Call duckdb_appender_error to obtain the error message followed by duckdb_appender_destroy to destroy the invalidated appender.

##### Syntax

    duckdb_state duckdb_appender_flush(
      duckdb_appender appender
    );

##### Parameters

- `appender`: The appender to flush.

##### Return Value

`DuckDBSuccess` on success or `DuckDBError` on failure.

#### `duckdb_appender_close`

Closes the appender by flushing all intermediate states and closing it for further appends. If flushing the data triggers a constraint violation or any other error, then all data is invalidated, and this function returns DuckDBError. Call duckdb_appender_error to obtain the error message followed by duckdb_appender_destroy to destroy the invalidated appender.

##### Syntax

    duckdb_state duckdb_appender_close(
      duckdb_appender appender
    );

##### Parameters

- `appender`: The appender to flush and close.

##### Return Value

`DuckDBSuccess` on success or `DuckDBError` on failure.

#### `duckdb_appender_destroy`

Closes the appender by flushing all intermediate states to the table and destroying it. By destroying it, this function de-allocates all memory associated with the appender. If flushing the data triggers a constraint violation, then all data is invalidated, and this function returns DuckDBError. Due to the destruction of the appender, it is no longer possible to obtain the specific error message with duckdb_appender_error. Therefore, call duckdb_appender_close before destroying the appender, if you need insights into the specific error.

##### Syntax

    duckdb_state duckdb_appender_destroy(
      duckdb_appender *appender
    );

##### Parameters

- `appender`: The appender to flush, close and destroy.

##### Return Value

`DuckDBSuccess` on success or `DuckDBError` on failure.

#### `duckdb_appender_begin_row`

A nop function, provided for backwards compatibility reasons. Does nothing. Only `duckdb_appender_end_row` is required.

##### Syntax

    duckdb_state duckdb_appender_begin_row(
      duckdb_appender appender
    );

#### `duckdb_appender_end_row`

Finish the current row of appends. After end_row is called, the next row can be appended.

##### Syntax

    duckdb_state duckdb_appender_end_row(
      duckdb_appender appender
    );

##### Parameters

- `appender`: The appender.

##### Return Value

`DuckDBSuccess` on success or `DuckDBError` on failure.

#### `duckdb_append_default`

Append a DEFAULT value (NULL if DEFAULT not available for column) to the appender.

##### Syntax

    duckdb_state duckdb_append_default(
      duckdb_appender appender
    );

#### `duckdb_append_bool`

Append a bool value to the appender.

##### Syntax

    duckdb_state duckdb_append_bool(
      duckdb_appender appender,
      bool value
    );

#### `duckdb_append_int8`

Append an int8_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_int8(
      duckdb_appender appender,
      int8_t value
    );

#### `duckdb_append_int16`

Append an int16_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_int16(
      duckdb_appender appender,
      int16_t value
    );

#### `duckdb_append_int32`

Append an int32_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_int32(
      duckdb_appender appender,
      int32_t value
    );

#### `duckdb_append_int64`

Append an int64_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_int64(
      duckdb_appender appender,
      int64_t value
    );

#### `duckdb_append_hugeint`

Append a duckdb_hugeint value to the appender.

##### Syntax

    duckdb_state duckdb_append_hugeint(
      duckdb_appender appender,
      duckdb_hugeint value
    );

#### `duckdb_append_uint8`

Append a uint8_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_uint8(
      duckdb_appender appender,
      uint8_t value
    );

#### `duckdb_append_uint16`

Append a uint16_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_uint16(
      duckdb_appender appender,
      uint16_t value
    );

#### `duckdb_append_uint32`

Append a uint32_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_uint32(
      duckdb_appender appender,
      uint32_t value
    );

#### `duckdb_append_uint64`

Append a uint64_t value to the appender.

##### Syntax

    duckdb_state duckdb_append_uint64(
      duckdb_appender appender,
      uint64_t value
    );

#### `duckdb_append_uhugeint`

Append a duckdb_uhugeint value to the appender.

##### Syntax

    duckdb_state duckdb_append_uhugeint(
      duckdb_appender appender,
      duckdb_uhugeint value
    );

#### `duckdb_append_float`

Append a float value to the appender.

##### Syntax

    duckdb_state duckdb_append_float(
      duckdb_appender appender,
      float value
    );

#### `duckdb_append_double`

Append a double value to the appender.

##### Syntax

    duckdb_state duckdb_append_double(
      duckdb_appender appender,
      double value
    );

#### `duckdb_append_date`

Append a duckdb_date value to the appender.

##### Syntax

    duckdb_state duckdb_append_date(
      duckdb_appender appender,
      duckdb_date value
    );

#### `duckdb_append_time`

Append a duckdb_time value to the appender.

##### Syntax

    duckdb_state duckdb_append_time(
      duckdb_appender appender,
      duckdb_time value
    );

#### `duckdb_append_timestamp`

Append a duckdb_timestamp value to the appender.

##### Syntax

    duckdb_state duckdb_append_timestamp(
      duckdb_appender appender,
      duckdb_timestamp value
    );

#### `duckdb_append_interval`

Append a duckdb_interval value to the appender.

##### Syntax

    duckdb_state duckdb_append_interval(
      duckdb_appender appender,
      duckdb_interval value
    );

#### `duckdb_append_varchar`

Append a varchar value to the appender.

##### Syntax

    duckdb_state duckdb_append_varchar(
      duckdb_appender appender,
      const char *val
    );

#### `duckdb_append_varchar_length`

Append a varchar value to the appender.

##### Syntax

    duckdb_state duckdb_append_varchar_length(
      duckdb_appender appender,
      const char *val,
      idx_t length
    );

#### `duckdb_append_blob`

Append a blob value to the appender.

##### Syntax

    duckdb_state duckdb_append_blob(
      duckdb_appender appender,
      const void *data,
      idx_t length
    );

#### `duckdb_append_null`

Append a NULL value to the appender (of any type).

##### Syntax

    duckdb_state duckdb_append_null(
      duckdb_appender appender
    );

#### `duckdb_append_data_chunk`

Appends a pre-filled data chunk to the specified appender.

The types of the data chunk must exactly match the types of the table, no casting is performed. If the types do not match or the appender is in an invalid state, DuckDBError is returned. If the append is successful, DuckDBSuccess is returned.

##### Syntax

    duckdb_state duckdb_append_data_chunk(
      duckdb_appender appender,
      duckdb_data_chunk chunk
    );

##### Parameters

- `appender`: The appender to append to.
- `chunk`: The data chunk to append.

##### Return Value

The return state.

##### About this page

- Report content issue
- Edit this page on GitHub