- Installation
- What's New in the Docs for 2.0
- Documentation
- Getting Started
- Connect
- Data Import and Export
- Overview
- Data Sources
- CSV Files
- IO
- 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
- Parquet Files
- Partitioning
- Appender
- INSERT Statements
- Lakehouse Formats
- Client APIs
- Overview
- ADBC
- 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
- Agent Mode
- Editing
- Friendly CLI
- Safe Mode
- Autocomplete
- Syntax Highlighting
- Known Issues
- Go
- Overview
- Connect
- Import Data
- Run Queries
- Handle Results
- Write User Defined Functions
- Profile and Monitor
- Troubleshoot
- Java (JDBC)
- Overview
- Connect
- Import Data
- Run Queries
- Handle Results
- Write User Defined Functions
- Profile and Monitor
- Deploy as Native Image
- Troubleshoot
- Node.js (Neo)
- ODBC
- Python
- Overview
- Data Ingestion
- Appender
- Conversion between DuckDB and Python
- DB API
- Relational API
- Function API
- Types API
- Expression API
- Spark API
- API Reference
- Known Python Issues
- Migrating to 2.0
- R
- Rust
- Overview
- Connect
- Import Data
- Run Queries
- Handle Results
- Write User Defined Functions
- Profile and Monitor
- Troubleshoot
- Wasm
- Tertiary Clients
- SQL
- Introduction
- Statements
- Overview
- ANALYZE
- ALTER DATABASE
- ALTER TABLE
- ALTER VIEW
- ATTACH and DETACH
- CALL
- CHECKPOINT
- COMMENT ON
- CONNECT and DISCONNECT
- COPY
- CREATE INDEX
- CREATE MACRO
- CREATE SCHEMA
- CREATE SECRET
- CREATE SEQUENCE
- CREATE TABLE
- CREATE VIEW
- CREATE TRIGGER
- CREATE TYPE
- DELETE
- DESCRIBE
- DROP
- EXPORT and IMPORT DATABASE
- INSERT
- LOAD / INSTALL
- MERGE INTO
- PIVOT
- Profiling
- PREPARE, EXECUTE, and DEALLOCATE
- SELECT
- SET / RESET
- SET VARIABLE
- SHOW and SHOW DATABASES
- SUMMARIZE
- Transaction Management
- UNPIVOT
- UPDATE
- UPDATE EXTENSIONS
- 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
- Geometry
- Interval
- List
- Literal Types
- Map
- NULL Values
- Numeric
- Struct
- Text
- Time
- Timestamp
- Time Zones
- Union
- Typecasting
- Variant
- Expressions
- Overview
- CASE Expression
- Casting
- Collations
- Comparisons
- IN Operator
- Logical Operators
- Star Expression
- Subqueries
- TRY
- Functions
- Overview
- Aggregate Functions
- Array Functions
- Bitstring Functions
- Blob Functions
- Date Format Functions
- Date Functions
- Date Part Functions
- Enum Functions
- Geometry 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
- Variant Functions
- Window Functions
- Constraints
- Indexes
- Meta Queries
- DuckDB's SQL Dialect
- Overview
- Indexing
- Friendly SQL
- Keywords and Identifiers
- Order Preservation
- PostgreSQL Compatibility
- SQL Quirks
- PEG Parser
- Samples
- Configuration
- Extensions
- Overview
- Installing Extensions
- Advanced Installation Methods
- Distributing Extensions
- Extension Repositories
- Community Extensions
- Versioning of Extensions
- Troubleshooting of Extensions
- Core Extensions
- Overview
- AutoComplete
- Avro
- AWS
- Azure
- Delta
- DuckLake
- Encodings
- Excel
- Full Text Search
- httpfs (HTTP and S3)
- Overview
- HTTP(S) Support
- Hugging Face
- S3 API Support
- S3 and AWS Authentication
- Legacy Authentication Scheme for S3 API
- Iceberg
- ICU
- inet
- Lance
- Legacy Parser
- MotherDuck
- MySQL
- ODBC
- Quack
- PostgreSQL
- Sirius
- Spatial
- SQLite
- SQLSmith
- TPC-DS
- TPC-H
- UI
- Unity Catalog
- Vortex
- VSS
- Quack Remote Protocol
- Guides
- Overview
- Data Viewers
- Database Integration
- File Formats
- Overview
- CSV Import
- CSV Export
- Directly Reading Files
- Directly Reading DuckDB Databases
- Excel Import
- Excel Export
- JSON Import
- JSON Export
- Parquet Import
- Parquet Export
- Querying Parquet Files
- File Access with the file: Protocol
- Meta Queries
- Describe Table
- EXPLAIN: Inspect Query Plans
- EXPLAIN ANALYZE: Profile Queries
- List Tables
- Summarize
- DuckDB Environment
- Network and Cloud Storage
- Overview
- HTTP Parquet Import
- HTTP CSV Import
- S3 Parquet Import
- S3 Parquet Export
- S3 Iceberg Import
- S3 Express One
- GCS Import
- Cloudflare R2 Import
- DuckDB over HTTPS / S3
- Share a Views-Only Database
- Fastly Object Storage Import
- SeaweedFS Import
- Tigris Import
- ODBC
- Performance
- Overview
- Environment
- Import
- Schema
- Indexing
- Join Operations
- File Formats
- How to Tune Workloads
- My Workload Is Slow
- Out-of-Memory Issues
- Benchmarks
- Working with Huge Databases
- Python
- Installation
- Executing SQL
- Jupyter Notebooks
- marimo 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
- Integration with PyTorch
- Using fsspec Filesystems
- SQL Editors
- Beekeeper Studio SQL Editor
- DBeaver SQL IDE
- DBine SQL Editor
- LibreDB Studio SQL Editor
- VisuaLeaf SQL Editor
- SQL Features
- AsOf Join
- Full-Text Search
- Graph Queries
- query and query_table Functions
- Merge Statement for SCD Type 2
- Timestamp Issues
- Snippets
- Creating Synthetic Data
- Dutch Railway Datasets
- Sharing Macros
- Analyzing a Git Repository
- Importing Duckbox Tables
- Copying an In-Memory Database to a File
- Calculating a Database Checksum
- Troubleshooting
- Glossary of Terms
- Browsing Offline
- Operations Manual
- Overview
- Migrating to DuckDB v2.0
- Backup Extension Repositories
- DuckDB's Footprint
- Installing DuckDB
- Logging
- User Agents
- Securing DuckDB
- Non-Deterministic Behavior
- Limits
- DuckDB Docker Container
- Development
- Overview
- DuckDB Repositories
- Release Cycle
- Metrics
- Profiling
- Building DuckDB
- Overview
- Build Configuration
- Building Extensions
- Statically Linking Extensions
- Android
- Linux
- macOS
- Raspberry Pi
- Windows
- Python
- R
- Troubleshooting
- Unofficial and Unsupported Platforms
- Benchmark Suite
- Testing
- Overview
- sqllogictest Introduction
- Writing Tests
- Unit Tester Configuration
- Debugging
- Result Verification
- Persistent Testing
- Loops
- Multiple Connections
- Catch
- Internal Errors
- Internals
- Sitemap
- Live Demo
The iceberg extension implements support for the Apache Iceberg open table format. There are two ways to work with Iceberg in DuckDB:
- Individual tables are read directly from storage, by pointing at a table's metadata. This requires no catalog and is read-only.
- Catalog-managed tables are accessed by attaching an Iceberg REST catalog. This unlocks the full feature set, including writing.
This page covers the basics of both. See also:
- Writing to Iceberg describes the supported write operations, partitioning and schema evolution.
- Iceberg Functions documents the functions provided by the extension.
- Iceberg Options documents the scan parameters,
ATTACHoptions, secret options and settings. - Catalogs explains how to attach an Iceberg REST Catalog, with instructions for specific catalogs.
- Troubleshooting lists common problems and their solutions.
Installing and Loading
The iceberg extension is installed and loaded automatically on first use.
If you would like to install and load it manually, run:
INSTALL AND LOAD iceberg;
Updating the Extension
The iceberg extension often receives updates between DuckDB releases.
To make sure that you have the latest version, update your extensions:
UPDATE EXTENSIONS;
Reading Iceberg Tables
Individual Iceberg tables can be read directly from storage with the iceberg_scan function, without attaching to a catalog. To test the examples, download the iceberg_data.zip file and unzip it.
Querying Individual Tables
Use the iceberg_scan function to read an Iceberg table from a path:
SELECT count(*)
FROM iceberg_scan('data/iceberg/lineitem_iceberg', allow_moved_paths = true);
| count_star() |
|---|
| 51793 |
The
allow_moved_pathsoption ensures that some path resolution is performed, which allows scanning Iceberg tables that are moved.
You can also directly specify the current manifest in the query, this may be resolved from the catalog prior to the query, in this example the manifest version is a UUID.
To do so, navigate to the data/iceberg directory and run:
SELECT count(*)
FROM iceberg_scan('lineitem_iceberg/metadata/v1.metadata.json');
| count_star() |
|---|
| 60175 |
For the full list of parameters accepted by iceberg_scan, see the Iceberg Options page.
Reading from Object Stores
The iceberg extension works together with the httpfs extension or the azure extension to access Iceberg tables in object stores such as S3 or Azure Blob Storage.
SELECT count(*)
FROM iceberg_scan('s3://bucketname/lineitem_iceberg/metadata/v1.metadata.json');
Metadata and Snapshots
To inspect the manifest entries and snapshots of a table, use the iceberg_metadata and iceberg_snapshots functions.
To read tables without a version-hint.text file or with non-standard metadata file names, see Selecting Metadata Versions.
Time Travel
To read a historical snapshot of a table, pass either snapshot_from_id or snapshot_from_timestamp (the two are mutually exclusive). Use iceberg_snapshots to list the available snapshots:
-- Read a specific snapshot by id
SELECT count(*)
FROM iceberg_scan('data/iceberg/lineitem_iceberg', snapshot_from_id = 7635660646343998149);
-- Read the snapshot that was current at a given time
SELECT count(*)
FROM iceberg_scan('data/iceberg/lineitem_iceberg', snapshot_from_timestamp = TIMESTAMP '2023-02-15 15:08:00');
Limitations of Direct Reads
- A version hint or explicit
versionis required to read a table, unless version guessing is enabled. - Only
gzip-compressed metadata is supported (viametadata_compression_codec = 'gzip').
Catalog Managed Tables
For full read and write access — and to use Iceberg's catalog features — attach an Iceberg REST catalog. Most catalogs authenticate with OAuth2; store the credentials in a secret and attach the catalog with ATTACH ... (TYPE iceberg, ...):
CREATE SECRET iceberg_secret (
TYPE iceberg,
CLIENT_ID 'admin',
CLIENT_SECRET 'password',
OAUTH2_SERVER_URI 'https://catalog.example.com/v1/oauth/tokens'
);
ATTACH 'warehouse' AS my_catalog (
TYPE iceberg,
SECRET iceberg_secret,
URI 'https://catalog.example.com'
);
Once attached, the catalog behaves like any other DuckDB database: reference its tables as catalog.schema.table and query or modify them with regular SQL.
SHOW ALL TABLES;
SELECT count(*) FROM my_catalog.default.events;
INSERT INTO my_catalog.default.events VALUES (1, 'click', now());
The metadata functions also work on catalog tables when passed a fully qualified name, e.g., iceberg_snapshots(my_catalog.default.events).
- For the full set of write operations — partitioning,
UPDATE,DELETE,MERGE INTO,ALTER TABLE, and table properties — see Writing to Iceberg. - For catalog-specific setup, see Catalogs. For the complete list of
ATTACHoptions and secret parameters, see Iceberg Options.
Time Travel
On an attached catalog, time travel with the AT clause directly on the table:
-- Using a snapshot id
SELECT * FROM my_catalog.default.events AT (VERSION => snapshot_id);
-- Using a timestamp
SELECT * FROM my_catalog.default.events AT (TIMESTAMP => TIMESTAMP '2025-09-22 12:32:43.217');
Interoperability with DuckLake
The iceberg_to_ducklake function performs a metadata-only copy of an attached Iceberg catalog into a DuckLake catalog, letting you query Iceberg tables as if they were DuckLake tables.