# CREATE DATABASE
> Create a database, zero-copy clone from an existing database, or import a local DuckDB file into MotherDuck.
The `CREATE DATABASE` statement creates a new database in MotherDuck.

It can be used for the following operations:
- Create a MotherDuck database from a local DuckDB database.
- Create a MotherDuck database from a remote DuckDB database file in cloud storage (for example, a file in Amazon S3).
- Create a MotherDuck database from another MotherDuck database or [share](/key-tasks/sharing-data/sharing-overview/) using zero-copy clone (without physically copying data).
:::note[Copy to local database]
To copy a MotherDuck database to a local database, use the [`COPY FROM DATABASE`](/sql-reference/motherduck-sql-reference/copy-database.md) statement.
:::

::::tip Zero-copy clone
When the source is another MotherDuck database or a share, `CREATE DATABASE ... FROM` performs a **zero-copy clone**. The command completes almost instantly because no data is physically duplicated. When the source is a local file, a remote file, or `CURRENT_DATABASE()`, data is physically copied to MotherDuck.
::::

:::warning
A share that carries an [include pattern](/key-tasks/sharing-data/table-level-security/) can't be a zero-copy clone source. A clone copies the underlying snapshot, which would carry the tables the pattern hides, so `CREATE DATABASE ... FROM` rejects a filtered share whether you name its attached alias or its share URL. To copy the tables the share does expose, use [`COPY FROM DATABASE`](/sql-reference/motherduck-sql-reference/copy-database.md) instead.
:::

## Syntax

```sql
CREATE [ OR REPLACE ] DATABASE [ IF NOT EXISTS ] <database name>
[
    FROM <database name> |
    FROM <snapshot_name> | <snapshot_id> | <snapshot_time>
    FROM '<local/file/path.db>' |
    FROM '<remote/file/path.db>' |
    FROM 'md:_share/...' |
    FROM CURRENT_DATABASE() -- Important: this command does not work with attached shares
]

[(
    [ TYPE { DEFAULT | DUCKLAKE | ICEBERG }, ]
    <option> [ <value> ] [, ...]
)];
```

`TYPE` selects the database type and defaults to `DEFAULT`, a native storage database. Which other options you can pass depends on the type, see [Database options](#database-options).

You can also pass the name of an attached share or a share URL as the database name, for example `CREATE DATABASE FROM my_share` or `CREATE DATABASE FROM 'md:_share/...'`.

If the database name already exists, the statement returns an error unless you specify `IF NOT EXISTS`.

Similar to DuckDB table name conventions, database names that start with a number or contain special characters must be double-quoted when used. Example: `CREATE DATABASE "123db"`

Creating a database does not change the active database. Run `USE DATABASE <database name>` to switch.

## Database options

Databases on MotherDuck are native storage databases, DuckLake databases, or Iceberg catalogs. Each type has its own set of options you can configure at creation time.

Note that `SNAPSHOT_RETENTION_DAYS` exists for both native storage and DuckLake databases, but means something different in each.

### Native storage options

All native storage databases have a transient status and a historical retention period. These properties are inherited on new databases created with the `CREATE DATABASE dest_db FROM source_db` syntax, so cloning a 0-day database produces another 0-day database. See [storage management](/concepts/storage-lifecycle#standard-databases) for what this means on Lite plans.

`CREATE OR REPLACE DATABASE dest_db FROM source_db` drops the destination and recreates it with the source's transient status and historical retention period. It does not preserve the destination's previous configuration. The same inheritance applies when cloning from an unfiltered share of a native database. To replace data while keeping the destination's configuration, use [`COPY FROM DATABASE (OVERWRITE)`](copy-database-overwrite.md#destination-configuration).

On the Business plan, set the historical retention period at creation, or change it later with [`ALTER DATABASE`](/sql-reference/motherduck-sql-reference/alter-database.md). On Lite plans, retention is fixed at the plan default and specifying a different value fails. You can set the transient status when creating a database, but it can't be altered after. Transient databases have a different failsafe period than non-transient databases.

| Name      | Description |
|------------|-------------|
| TYPE DEFAULT | Optional. Any database created without a `TYPE` is a native storage database. |
| TRANSIENT  | Specify `TRANSIENT` at database creation to enable transient storage. Refer to the [Storage lifecycle management overview](/concepts/storage-lifecycle#transient-databases) for more details. |
| SNAPSHOT_RETENTION_DAYS | Business plan only. Provide an integer to specify the number of days to retain automatic and unnamed snapshots as `historical_bytes`. Named snapshots are retained until unnamed. Refer to the [Storage lifecycle management overview](/concepts/storage-lifecycle#storage-management) for more details. |

```sql
-- A native storage database:
CREATE DATABASE cloud_db;

-- A transient database:
CREATE DATABASE scratch_db (TRANSIENT);

-- A database that keeps seven days of snapshots:
CREATE DATABASE archive_db (SNAPSHOT_RETENTION_DAYS 7);
```

### DuckLake options

| Name      | Description |
|------------|-------------|
| TYPE DUCKLAKE | Specify `TYPE DUCKLAKE` at database creation to create a DuckLake. Omit `DATA_PATH` for fully managed storage. Refer to the [DuckLake overview](/integrations/file-formats/ducklake/) for more details. |
| DATA_PATH | Optional path in your own Amazon S3, Cloudflare R2, Azure Blob Storage, or Google Cloud Storage (for example, `DATA_PATH 's3://<bucket_name>/<ducklake_prefix>/'`). Cross-region and cross-cloud storage are supported. See [BYOB setup and credentials](/integrations/file-formats/ducklake/#bring-your-own-bucket). |
| ENCRYPTED | Enables encryption for DuckLake storage. To enable it, specify `ENCRYPTED` at database creation. Refer to [Encryption](https://ducklake.select/docs/stable/duckdb/advanced_features/encryption) for more details. |
| DATA_INLINING_ROW_LIMIT | Row-count threshold for inline data storage. Defaults to 10 rows. Set to 0 to disable inlining. See [data inlining](/integrations/file-formats/ducklake/#data-inlining). |
| SNAPSHOT_RETENTION_DAYS | Number of days to retain DuckLake snapshots before they are eligible for expiration. Defaults to `NULL` (infinite retention). DuckLake snapshots are expired by running [maintenance operations](/concepts/ducklake#maintenance) manually; MotherDuck does not expire them automatically. |

```sql
-- A fully managed DuckLake:
CREATE DATABASE cloud_ducklake (TYPE DUCKLAKE);

-- A DuckLake that keeps seven days of snapshots:
CREATE DATABASE my_ducklake (TYPE DUCKLAKE, SNAPSHOT_RETENTION_DAYS 7);

-- A DuckLake in your own bucket, with encryption:
CREATE DATABASE my_encrypted_ducklake
(
    TYPE DUCKLAKE,
    DATA_PATH 's3://my-bucket/ducklake',
    ENCRYPTED
);
```

### Iceberg catalog options

Refer to [Apache Iceberg](/integrations/file-formats/apache-iceberg#persisted-iceberg-catalogs) for the full set of catalog options and examples.

| Name      | Description |
|------------|-------------|
| TYPE ICEBERG | Specify `TYPE ICEBERG` to attach an Iceberg REST catalog as a persisted MotherDuck database. |
| SECRET | Required. Name of the MotherDuck Iceberg or S3 secret holding catalog credentials. `secret` is a reserved word, so quote it as `"secret"`. |
| DEFAULT_SCHEMA | Required. Schema used to resolve unqualified table names. Must exist in the catalog. |
| ENDPOINT | URL of the Iceberg REST catalog. Required unless set in the secret or derived from `endpoint_type`. |
| WAREHOUSE | Catalog warehouse identifier. For S3 Tables, the bucket ARN. |
| ENDPOINT_TYPE | Selects a well-known catalog flavor, for example `'s3_tables'` or `'glue'`. |
| DEFAULT_REGION | Per-catalog region override. Defaults to your MotherDuck org region. |
| READ_ONLY | Attach the catalog as read-only. |
| ACCESS_DELEGATION_MODE | Controls vended-credential delegation, for example `'none'`. |

```sql
-- Attach an Iceberg REST catalog as a persisted database:
CREATE DATABASE my_datalake
(
    TYPE ICEBERG,
    "secret" my_iceberg_secret,
    ENDPOINT 'https://my-catalog.example.com',
    WAREHOUSE 'my_warehouse',
    DEFAULT_SCHEMA 'default'
);
```

## Source database options

These options are only available for native MotherDuck databases. They apply to the source database that is being cloned.

Snapshot selectors are only supported when cloning a native MotherDuck database. They are not supported for DuckLake databases. Cloning a DuckLake database with `CREATE DATABASE ... FROM` is supported, but the resulting database is a native storage database containing a copy of the data, not a DuckLake. To read a DuckLake or Iceberg database as of a historical snapshot instead of cloning it, use the per-query `AT` clause. See [DuckLake time travel](/integrations/file-formats/ducklake#time-travel) and [Iceberg time travel](/integrations/file-formats/apache-iceberg#time-travel).

| Name | Data Type | Value                             |
|-------------|-----------|-----------------------------------|
| SNAPSHOT_TIME | TIMESTAMP    | Selects the newest snapshot created before or at this timestamp |
| SNAPSHOT_ID | UUID    | ID of the snapshot to clone |
| SNAPSHOT_NAME | STRING    | Name of the snapshot to clone |

## Example usage

To create an empty database:

```sql
CREATE DATABASE empty_ducks;
```

If the database name already exists, the statement fails unless you use `OR REPLACE` or `IF NOT EXISTS`.

```sql
CREATE DATABASE ducks;
-- Succeeds if 'ducks' does not exist

CREATE DATABASE ducks;
-- Error: Failed to create database: database with name 'ducks' already exists

CREATE OR REPLACE DATABASE ducks; -- Replaces existing 'ducks' with an empty database

CREATE DATABASE IF NOT EXISTS ducks; -- No-op if 'ducks' already exists
```

To *copy* an entire database from your local DuckDB instance into MotherDuck:

```sql
USE ducks_db;
CREATE DATABASE ducks FROM CURRENT_DATABASE();

-- Or alternatively, use the following command - if ducks_db exists, even if populated, it will be replaced with an empty one:
CREATE OR REPLACE DATABASE ducks FROM ducks_db;

-- In the following, if ducks_db exists, the operation will be skipped, but it will not error:
CREATE DATABASE IF NOT EXISTS ducks_db;
```

For examples of the per-type creation options, see [Database options](#database-options).

To zero-copy clone a database that is already attached in MotherDuck:

```sql
CREATE DATABASE cloud_db FROM another_cloud_db;
```

To zero-copy clone a past snapshot of a database in MotherDuck

```sql
CREATE DATABASE cloud_db FROM another_cloud_db (SNAPSHOT_NAME 'prod_backup');
CREATE DATABASE cloud_db FROM another_cloud_db (SNAPSHOT_ID '3f2504e0-4f89-11d3-9a0c-0305e82c3301');
CREATE DATABASE cloud_db FROM another_cloud_db (SNAPSHOT_TIME '2025-07-29 14:30:25.123456');
```

To upload a local DuckDB database file:

```sql
CREATE DATABASE flying_ducks FROM './databases/local_ducks.db';
```

To create a database from a remote DuckDB database file in cloud storage:

```sql
CREATE DATABASE flying_ducks FROM 's3://my-bucket/ducks.db';
```

Reading from private cloud storage uses a configured [secret](/sql-reference/motherduck-sql-reference/create-secret/).

To upload an attached local DuckDB database:

```sql
ATTACH './databases/local_ducks.db';
CREATE DATABASE flying_ducks FROM local_ducks;
```


---

## 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=%2Fsql-reference%2Fmotherduck-sql-reference%2Fcreate-database%2F&page_title=CREATE%20DATABASE&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.
