---
title: Seed TPC-H data into Unity Catalog
summary: Generate the eight-table TPC-H benchmark dataset with DuckDB, write it
  as Delta tables, and register them in Unity Catalog as samples.tpch.
diataxis: how-to
project: unitycatalog
canonical: https://docs.unitycatalog.io/how-to/seed-tpch-data
companions:
  - url: "https://docs.unitycatalog.io/how-to/seed-tpch-data/seed_tpch.py"
    kind: python
    purpose: "Seed the classic TPC-H dataset into Unity Catalog as governed Delta tables."
    run: "UNITY_CATALOG_URL=http://localhost:8080/api/2.1/unity-catalog uv run https://docs.unitycatalog.io/how-to/seed-tpch-data/seed_tpch.py"
    requires-python: ">=3.11"
    services: ["unitycatalog"]
environment:
  title: "Unity Catalog 0.7.0"
  dir: "uc-docs-env/unitycatalog"
  start: ["curl -fsSL https://docs.unitycatalog.io/env/unitycatalog.tar.gz | tar -xz", "cd uc-docs-env/unitycatalog && docker compose up -d --wait", "export UNITY_CATALOG_URL=http://localhost:8080/api/2.1/unity-catalog"]
  stop: "docker compose down"
  elements: ["unityCatalogOSS"]
  index: "https://docs.unitycatalog.io/env/environments.json"
---

## Companion files

CI-tested scripts that run this page's examples end to end. A script that exits 0 has passed its checks.

They need Unity Catalog 0.7.0 running. To start it (also `environment` in this file's frontmatter):

```bash
curl -fsSL https://docs.unitycatalog.io/env/unitycatalog.tar.gz | tar -xz
cd uc-docs-env/unitycatalog && docker compose up -d --wait
export UNITY_CATALOG_URL=http://localhost:8080/api/2.1/unity-catalog
```

- [`seed_tpch.py`](https://docs.unitycatalog.io/how-to/seed-tpch-data/seed_tpch.py) (Python): Seed the classic TPC-H dataset into Unity Catalog as governed Delta tables.
  - run: `UNITY_CATALOG_URL=http://localhost:8080/api/2.1/unity-catalog uv run https://docs.unitycatalog.io/how-to/seed-tpch-data/seed_tpch.py`

[TPC-H](https://www.tpc.org/tpch/) is the standard benchmark schema: eight related tables (`region`, `nation`, `supplier`, `customer`, `part`, `partsupp`, `orders`, and `lineitem`) modeling a wholesale supplier. Seeded into [Unity Catalog](https://docs.unitycatalog.io/explanation/what-is-unity-catalog "The open-source reference server implementing the Unity Catalog specification."), it gives joins, access grants, and cross-engine queries data that looks like a real business.

This guide generates TPC-H with DuckDB, writes each table as Delta, and registers it as an external table, three steps per table:

> **generate** (DuckDB) → **write Delta** (deltalake) → **register** (Unity Catalog)

> **Prerequisites**
>
> - [Docker](https://docs.docker.com/get-started/get-docker/) with Compose v2, for the local environment.
> - Unity Catalog 0.7.0, running: [Run a local Unity Catalog server](https://docs.unitycatalog.io/how-to/run-local-server).
> - [uv](https://docs.astral.sh/uv/getting-started/installation/).

Unity Catalog only records where an external table lives and never reads the files itself, so the script writes the Delta tables to a local directory it owns (override with `TPCH_STORAGE_ROOT`).

### Step 1 — Generate TPC-H

[DuckDB](https://duckdb.org/docs/stable/core_extensions/tpch) ships a `tpch` extension that generates the benchmark data in-process. `dbgen(sf = ...)` builds every table at the given **scale factor** (`0.01` here keeps it small and fast; bump it for more data), and each table comes straight back as an Arrow table.

`seed_tpch.py`

```python
con = duckdb.connect()  # in-memory
con.execute("INSTALL tpch; LOAD tpch;")
con.execute(f"CALL dbgen(sf = {sf})")  # deterministic for a given scale factor
tables = {name: con.table(name).to_arrow_table() for name in TPCH_TABLES}
```

### Step 2 — Write each table as Delta

Point [`write_deltalake`](https://delta-io.github.io/delta-rs/) at a location under the storage root and hand it the Arrow table. That writes a real Delta table — transaction log and all — and returns its `file://` URI.

`seed_tpch.py`

```python
location = root / name
write_deltalake(location, arrow, mode="overwrite")
```

### Step 3 — Register the tables in Unity Catalog

Connect with the async SDK, then create the catalog `samples` with the schema `tpch`. For each Delta table written, register an **external** table, with the column list derived from the table's Arrow schema. The tables are then `samples.tpch.lineitem`, `samples.tpch.orders`, and so on.

`seed_tpch.py`

```python
await catalogs.create_catalog(
    CreateCatalog(name="samples", comment="TPC-H dataset")
)
await schemas.create_schema(CreateSchema(name="tpch", catalog_name="samples"))

# Register each Delta table we wrote as an EXTERNAL table Unity Catalog
# governs — UC stores the schema and location, the data stays in Delta.
for name, arrow in arrow_tables.items():
    await tables.create_table(
        CreateTable(
            name=name,
            catalog_name="samples",
            schema_name="tpch",
            table_type=TableType.EXTERNAL,
            data_source_format=DataSourceFormat.DELTA,
            storage_location=locations[name],
            columns=arrow_to_columns(arrow.schema),
        )
    )
    print(f"registered samples.tpch.{name}")
```

> **Tip**
>
> The `arrow_to_columns` helper (just above `main` in the script) maps Arrow types to Unity Catalog column types and builds the `type_json` each column needs — including the `metadata` field the server requires.

### Step 4 — Verify the catalog

List the schema's tables to confirm all eight registered, then read one straight back from Delta to prove the data is really there.

`seed_tpch.py`

```python
listed = await tables.list_tables(catalog_name="samples", schema_name="tpch")
registered = sorted(t.name for t in listed.tables or [])
print(f"{len(registered)} tables in samples.tpch: {registered}")

# Read a table straight back from Delta to prove the data is really there.
lineitem_rows = DeltaTable(locations["lineitem"]).to_pyarrow_table().num_rows
print(f"lineitem has {lineitem_rows} rows")
```

## Next steps

You now have an eight-table TPC-H dataset in Unity Catalog. To regenerate it at a larger scale, raise the `sf` argument to `main` (for example `0.1` for about 600,000 `lineitem` rows) and run the script again; it replaces the earlier tables.

- [Read and write Unity Catalog tables from DuckDB](https://docs.unitycatalog.io/how-to/duckdb) queries the tables by name.
- [Query Unity Catalog tables from Python DataFrame libraries](https://docs.unitycatalog.io/how-to/python-dataframes) reads them from Polars, Daft, or pandas.
