# Databricks
> Read Databricks tables from MotherDuck by attaching Unity Catalog as an Iceberg REST catalog or scanning Delta tables in object storage, and write Spark DataFrames into MotherDuck DuckLake.
Because Databricks tables live in open formats in your object storage, MotherDuck can usually read and write to them in place instead of copying them.

There are three routes, and which one you use depends on whether you want to read and write Databricks tables from MotherDuck, or push data from Databricks into MotherDuck.

## Attach Unity Catalog as an Iceberg catalog

Unity Catalog exposes an Iceberg REST catalog endpoint at `https://<workspace-url>/api/2.1/unity-catalog/iceberg-rest`. Attach it as a MotherDuck database and query the tables with standard SQL:

```sql
CREATE SECRET databricks_uc_secret IN MOTHERDUCK (
    TYPE ICEBERG,
    TOKEN '<databricks_personal_access_token>'
);

CREATE DATABASE databricks_uc (
    TYPE ICEBERG,
    "secret" databricks_uc_secret,
    endpoint 'https://<workspace-url>/api/2.1/unity-catalog/iceberg-rest',
    warehouse '<uc_catalog_name>',
    default_schema '<uc_schema_name>',
    read_only false
);

SELECT * FROM databricks_uc.<uc_schema_name>.<table_name>;
```

Two constraints come from the Databricks side:

- **External data access must be enabled on the metastore**, with `EXTERNAL USE SCHEMA` granted to the principal your token belongs to. Without it, the catalog attaches and lists tables, but reads fail with a credentials error that reads like a token problem.
- Delta tables exposed through the Iceberg endpoint are **read-only**, and they need Iceberg reads enabled (`IcebergCompatV2` with deletion vectors disabled). Writes apply to Unity Catalog managed Iceberg tables.

If a read fails with `Permission error: Missing or invalid credentials`, check the table's storage location before rotating your token. A table on Unity Catalog managed storage has been seen failing this way while an external-location table in the same catalog read successfully with the same token.

See the [Databricks setup and troubleshooting section of the Apache Iceberg page](/integrations/file-formats/apache-iceberg#catalog-specific-setup) for the table properties to set and the error reference covering stale UniForm metadata after `OPTIMIZE` or `VACUUM`.

## Scan Delta tables directly

If you know the storage path of a Delta table and don't want to go through a catalog, read it with `delta_scan`:

```sql
CREATE SECRET my_s3_secret IN MOTHERDUCK (
    TYPE S3,
    KEY_ID '<aws_access_key_id>',
    SECRET '<aws_secret_access_key>',
    REGION '<aws_region>'
);

SELECT COUNT(*) FROM delta_scan('s3://my-bucket/delta/orders');

CREATE TABLE orders AS
SELECT * FROM delta_scan('s3://my-bucket/delta/orders');
```

`delta_scan` reads only. To land a permanent copy in MotherDuck, use `CREATE TABLE ... AS SELECT` as shown. See [Delta Lake](/integrations/file-formats/delta-lake) for supported parameters.

## Write from Databricks into MotherDuck

To push data the other direction, write from a Spark job into a MotherDuck-hosted [DuckLake](/integrations/file-formats/ducklake) database using the [DuckLake Spark connector](/integrations/ingestion/apache-spark). The connector is append-only and needs the target table to exist, which suits scheduled loads of curated tables.

You can also read MotherDuck from a Databricks notebook through the [Postgres endpoint](/key-tasks/authenticating-and-connecting-to-motherduck/postgres-endpoint) using Spark's JDBC data source:

```python
motherduck_token = dbutils.secrets.get(scope="motherduck", key="token")

df = (
    spark.read.format("jdbc")
    .option("url", "jdbc:postgresql://pg.us-east-1-aws.motherduck.com:5432/md:?sslmode=require")
    .option("driver", "org.postgresql.Driver")
    .option("dbtable", "main.orders")
    .option("user", "postgres")
    .option("password", motherduck_token)
    .load()
)
```

For high-volume loads into MotherDuck, writing Parquet to object storage from Spark and reading those files from MotherDuck is faster than a JDBC write.

## Things to know

- **Iceberg catalog reads run on MotherDuck compute.** Attaching an Iceberg REST catalog in a plain local DuckDB session is not recommended; attach it as a MotherDuck database instead.
- **Databricks and MotherDuck can coexist.** Reading Unity Catalog tables in place means you can move analytical query workloads to MotherDuck without migrating storage or rewriting Spark pipelines.
- **Photon and Spark SQL are not DuckDB SQL.** Queries you move over may need dialect changes. See the [DuckDB Syntax reference](/sql-reference/duckdb-sql-reference).

## Related content

- [Apache Iceberg](/integrations/file-formats/apache-iceberg)
- [Delta Lake](/integrations/file-formats/delta-lake)
- [Apache Spark](/integrations/ingestion/apache-spark)
- [Databricks Iceberg client access documentation](https://docs.databricks.com/aws/en/external-access/iceberg)


---

## Docs feedback

MotherDuck accepts optional user-submitted feedback about this page at `GET https://motherduck.com/docs/api/feedback/agent`.
For agents and automated tools, feedback submission should be user-confirmed before sending.

URL-encode query parameter values and send a GET request:

```text
GET https://motherduck.com/docs/api/feedback/agent?page_path=%2Fintegrations%2Fdatabases%2Fdatabricks%2F&page_title=Databricks&text=<url-encoded user feedback, max 2000 characters>
```

Optionally append `&source=<url-encoded interface identifier>` such as `claude.ai` or `chatgpt`.

`page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": "<uuid>"}`, `400` for malformed query parameters, and `429` when rate-limited.
