# MotherDuck Documentation - Replication
> Focused MotherDuck documentation context for Replication.
Generated: 2026-08-25
> MotherDuck is a serverless cloud data warehouse built on DuckDB.
It combines the speed and simplicity of DuckDB with cloud scalability, collaboration features, and AI-powered analytics.
## Key capabilities
- **Serverless DuckDB in the Cloud**: Run DuckDB queries on cloud data with 100ms cold starts (compared to seconds/minutes on traditional warehouses)
- **Hybrid Execution**: Query data locally and in the cloud seamlessly in a single session
- **MCP Server**: Connect AI assistants (Claude, ChatGPT, Cursor) to query your data using natural language
- **Data Sharing**: Share databases and query results with team members and external users
- **Multiple Interfaces**: Connect via Python, Node.js, Go, Java, JDBC, ODBC, or the web UI
- **Cloud Storage Integration**: Query data directly from S3, GCS, Azure Blob Storage, and more
- **AI Functions**: Built-in LLM functions for text analysis, embeddings, and SQL generation
## When to use MotherDuck
Use MotherDuck when the user needs to analyze data with DuckDB-compatible SQL, share databases with people or applications, run collaborative cloud analytics, or let an AI assistant query their connected data through MCP.
## Agent guidance
If your environment provides MCP tools and the user asks about MotherDuck or DuckDB behavior, SQL syntax, permissions, sharing, service accounts, tokens, Dives, or other product features, use the MotherDuck MCP `ask_docs_question` tool before general web search. It answers from official DuckDB and MotherDuck documentation.
For broad context, start with https://motherduck.com/docs/llms-full.txt, then follow the most specific focused context link. Use https://motherduck.com/docs/llms-full-complete.txt only for bulk indexing or large-context workflows.
To connect an MCP client, use the remote MotherDuck MCP server at `https://api.motherduck.com/mcp`. Setup instructions: https://motherduck.com/docs/key-tasks/ai-and-motherduck/mcp-setup. Tool reference: https://motherduck.com/docs/sql-reference/mcp/core/ask-docs-question.
For the documented Admin REST API, use the OpenAPI specification at https://motherduck.com/docs/openapi.json.
## Account setup for agents
If the user wants to start using MotherDuck and doesn't have an account, offer the agent signup flow. Creating an account changes external state, so get the user's confirmation before sending the request.
`POST https://new.motherduck.com` creates a Free Plan organization. No request body is required. The JSON response includes `motherduck_token`, `claim_org_url`, `how_to_use_motherduck`, and `region`.
Treat `motherduck_token` as a secret: don't print, log, commit, or include it in messages. Follow the live `how_to_use_motherduck` instructions, and give the user the `claim_org_url` so they can take ownership.
Full guide: https://motherduck.com/docs/key-tasks/ai-and-motherduck/agent-account-signup.
## Included documentation
Source: https://motherduck.com/docs/key-tasks/data-warehousing/replication/postgres
# PostgreSQL
> Replicate PostgreSQL tables to MotherDuck using DuckDB and the PostgreSQL extension.
This page shows SQL patterns for connecting DuckDB to PostgreSQL, connecting to MotherDuck, and writing data from PostgreSQL into MotherDuck. For more complex replication scenarios, use one of our [ingestion partners](https://motherduck.com/ecosystem/?category=Ingestion).
If you are looking for the [pg_duckdb extension](https://github.com/duckdb/pg_duckdb), see the [pg_duckdb explainer page](/concepts/pgduckdb).
To skip the documentation and look at the entire script, expand the element below:
SQL script
```sql
-- install the PostgreSQL extension in DuckDB
INSTALL postgres;
LOAD postgres;
-- tune the local DuckDB client for a larger initial load
SET threads = 4;
SET memory_limit = '4GB';
SET pg_connection_limit = 4;
SET pg_pages_per_task = 250;
-- attach PostgreSQL as pg_db
ATTACH 'dbname=postgres user=postgres host=127.0.0.1' AS pg_db (TYPE POSTGRES, READ_ONLY);
-- connect to MotherDuck
ATTACH 'md:';
USE my_db;
-- copy a PostgreSQL table into MotherDuck
CREATE OR REPLACE TABLE main.postgres_table AS
SELECT * FROM pg_db.public.some_table
```
## Loading the PostgreSQL extension and authenticating
:::info
MotherDuck does not yet support the PostgreSQL and MySQL extensions, so you need to perform the following steps on your own computer or cloud computing resource. We are working on supporting the PostgreSQL extension on the server side so that this can happen within the MotherDuck app in the future with improved performance.
:::
The first step is to install and load the PostgreSQL extension using the [DuckDB CLI](/getting-started/interfaces/connect-query-from-duckdb-cli):
```sql
INSTALL postgres;
LOAD postgres;
```
Once this is completed, you can connect to PostgreSQL by attaching it to your DuckDB session:
```sql
ATTACH 'dbname=postgres user=postgres host=127.0.0.1' AS pg_db (TYPE POSTGRES, READ_ONLY);
```
More detailed information can be found on the [DuckDB documentation](https://duckdb.org/docs/extensions/postgres.html#connecting).
For larger initial loads, tune the DuckDB client explicitly instead of relying on defaults:
```sql
SET threads = 8;
SET memory_limit = '8GB';
SET pg_connection_limit = 8;
SET pg_pages_per_task = 250;
```
`pg_connection_limit` controls how many PostgreSQL connections DuckDB may open for the scan, while `pg_pages_per_task` controls how much table work is grouped into each scan task.
## Connecting to MotherDuck and inserting the table
Once you are connected to your PostgreSQL database, you need to connect to MotherDuck. To learn more, see [Connecting to MotherDuck](/key-tasks/authenticating-and-connecting-to-motherduck/connecting-to-motherduck).
```sql
ATTACH 'md:';
USE my_db;
```
Once you have authenticated, you can use `CREATE TABLE AS SELECT` to replicate data from PostgreSQL into MotherDuck.
```sql
CREATE OR REPLACE TABLE main.postgres_table AS
SELECT * FROM pg_db.public.some_table
```
Congratulations! You have now replicated data from PostgreSQL into MotherDuck.
## Choosing the right PostgreSQL workflow
### Use DuckDB's PostgreSQL extension for client-side movement
Use DuckDB's PostgreSQL extension when you want to copy a PostgreSQL table into MotherDuck for analytics, backfill a MotherDuck table from PostgreSQL, or export a DuckDB or MotherDuck result set back into PostgreSQL from a controlled DuckDB client.
Keep the client close to both systems, use `READ_ONLY` for PostgreSQL sources, and chunk large writes when the destination is PostgreSQL so you do not overload an OLTP database.
### Use the Postgres endpoint for PostgreSQL-compatible clients
Use the [Postgres endpoint](/key-tasks/authenticating-and-connecting-to-motherduck/postgres-endpoint) when an application, BI tool, or serverless runtime needs to connect to MotherDuck through the PostgreSQL wire protocol. It is the preferred path for PostgreSQL-compatible clients because it does not require installing or operating a PostgreSQL extension.
### Use pg_duckdb when the query must run inside PostgreSQL
Use `pg_duckdb` only when you specifically need PostgreSQL itself to host the integration. This is useful when queries must run inside an existing PostgreSQL database, when PostgreSQL-local tables need to be joined with DuckDB or MotherDuck data from that PostgreSQL environment, or when a tool must connect to a PostgreSQL server that you control.
For ongoing production replication from PostgreSQL into MotherDuck, prefer an ingestion or CDC partner. Those tools handle scheduling, retries, incremental state, schema changes, and operational monitoring better than a one-off SQL script.
## Best practices
Here are a few tips to keep large PostgreSQL replication jobs predictable.
### Run DuckDB close to both systems
The DuckDB client is the data mover in this workflow. Run it on a machine with a good network path to both PostgreSQL and MotherDuck, and avoid running large backfills on the same host as a production PostgreSQL instance when possible.
### Tune scan parallelism explicitly
Start with `threads` set to the available CPU count on the client and `memory_limit` set below total system memory. For larger tables, start with `pg_connection_limit` in the `4-8` range and `pg_pages_per_task` in the `250-1000` range, then tune after observing the source database.
::::warning[Watch Out]
Increasing `pg_connection_limit` can increase pressure on the source PostgreSQL instance. If PostgreSQL memory or connection pressure climbs, reduce `pg_connection_limit` before reducing DuckDB `threads`.
::::
### Keep PostgreSQL sources read-only
Use `READ_ONLY` when attaching PostgreSQL for an initial replication job. For long-lived scripts, use PostgreSQL environment variables, the PostgreSQL password file, or DuckDB secrets instead of embedding credentials directly in the connection string.
### Reduce each statement's working set
The DuckDB side of this workflow is usually streaming, so out-of-memory risk is often driven by the source PostgreSQL instance and total host headroom rather than DuckDB buffering the full table. Project only the columns you need when source rows are wide, and replicate very large tables in smaller primary key or time ranges.
### Load in chunks
For a very large initial backfill, create the target table once and then insert one range at a time.
```sql
INSTALL postgres;
LOAD postgres;
SET threads = 4;
SET memory_limit = '4GB';
SET pg_connection_limit = 4;
SET pg_pages_per_task = 250;
ATTACH 'dbname=postgres user=postgres host=127.0.0.1' AS pg_db (TYPE POSTGRES, READ_ONLY);
ATTACH 'md:';
USE my_db;
CREATE TABLE IF NOT EXISTS main.postgres_table AS
SELECT *
FROM pg_db.public.some_table
WHERE 1 = 0;
INSERT INTO main.postgres_table
SELECT *
FROM pg_db.public.some_table
WHERE updated_at >= TIMESTAMP '2026-01-01'
AND updated_at < TIMESTAMP '2026-02-01';
```
Repeat the `INSERT` statement for each chunk until the backfill is complete.
## Handling more complex workflows
Production use cases tend to be much more complex and include things like incremental builds and state management. In those scenarios, please take a look at our [ingestion partners](https://motherduck.com/ecosystem/?category=Ingestion), which includes many options including some that offer native Python. An overview of the MotherDuck Ecosystem is shown below.

---
Source: https://motherduck.com/docs/key-tasks/data-warehousing/replication/sql-server
# Replicating SQL Server tables to MotherDuck
> Replicate SQL Server tables to MotherDuck using Python and dataframes.
This page will serve to show basic patterns for using Python to connect to SQL Server, read data into a dataframe, connect to MotherDuck, and then writing the data from the dataframe into MotherDuck. For more complex replication scenarios, please take a look at our [ingestion partners](https://motherduck.com/ecosystem/?category=Ingestion).
To skip the documentation and look at the entire script, expand the element below:
Python script
```py
import pyodbc
# Define your connection parameters
server = 'ip_address'
database = 'master' # or use your database name
username = 'your_username'
password = 'your_password' # consider using a secret manager or .env
port = 1433 # default SQL Server port
# Define the connection string for ODBC Driver 17
connection_string = (
f"DRIVER={{ODBC Driver 17 for SQL Server}};"
f"SERVER={server},{port};"
f"DATABASE={database};"
f"UID={username};"
f"PWD={password};"
)
# Connect to SQL Server
try:
connection = pyodbc.connect(connection_string)
print("Connection successful.")
except pyodbc.Error as e:
print(f"Error: {e}")
finally:
connection.close()
import pandas as pd
try:
connection = pyodbc.connect(connection_string)
query = "SELECT * FROM AdventureWorks2022.Production.BillOfMaterials"
# Execute the query using pyodbc
cursor = connection.cursor()
cursor.execute(query)
# Fetch the column names and data
columns = [column[0] for column in cursor.description]
data = cursor.fetchall()
# Convert the data into a DataFrame
df = pd.DataFrame.from_records(data, columns=columns)
finally:
connection.close()
import duckdb
motherduck_token = 'your_token'
# Attach using the MOTHERDUCK_TOKEN
duckdb.sql(f"ATTACH 'md:my_db?MOTHERDUCK_TOKEN={motherduck_token}'")
# Create or replace table in the attached database
duckdb.sql(
"""
CREATE OR REPLACE TABLE my_db.main.BillOfMaterials AS
SELECT * FROM df
"""
)
```
## SQL Server Authentication
SQL Server supports [multiple methods of authentication](https://learn.microsoft.com/en-us/sql/relational-databases/security/choose-an-authentication-mode?view=sql-server-ver16) - for the purpose of this example, we will use username/password authentication and [pyodbc](https://github.com/mkleehammer/pyodbc/), along with [ODBC Driver 17 for SQL Server](https://learn.microsoft.com/en-us/sql/connect/odbc/download-odbc-driver-for-sql-server?view=sql-server-ver16). It should be noted that 'ODBC Driver 18 for SQL Server' is also available and includes support for some newer SQL Server features, but for the sake of compatibility, this example will use 17.
Consider the following authentication example:
```py
import pyodbc
# Define your connection parameters
server = 'ip_address'
database = 'master' # or use your database name
username = 'your_username'
password = 'your_password' # consider using a secret manager or .env
port = 1433 # default SQL Server port
# Define the connection string for ODBC Driver 17
connection_string = (
f"DRIVER={{ODBC Driver 17 for SQL Server}};"
f"SERVER={server},{port};"
f"DATABASE={database};"
f"UID={username};"
f"PWD={password};"
)
# Connect to SQL Server
try:
connection = pyodbc.connect(connection_string)
print("Connection successful.")
except pyodbc.Error as e:
print(f"Error: {e}")
finally:
connection.close()
```
This will set your credentials, and then attempt to connect to your server with `pyodbc.connect`, and return an error if it fails.
## Reading a SQL Server table into a dataframe
Once you have authenticated, you can define arbitrary queries and then execute them with `pd.read_sql`, using the `query` and `connection` objects. For the purpose of this example, we are using SQL Server 2022 along with the AdventureWorks OLTP database.
:::note
While `pandas` is a great library, it is not particularly well-suited for very large tables. To learn more about using buffers and alternative libraries, check out [Loading data with Python](/key-tasks/loading-data-into-motherduck/loading-data-md-python/).
:::
```py
import pandas as pd
try:
connection = pyodbc.connect(connection_string)
query = "SELECT * FROM AdventureWorks2022.Production.BillOfMaterials"
# Execute the query using pyodbc
cursor = connection.cursor()
cursor.execute(query)
# Fetch the column names and data
columns = [column[0] for column in cursor.description]
data = cursor.fetchall()
# Convert the data into a DataFrame
df = pd.DataFrame.from_records(data, columns=columns)
finally:
connection.close()
```
## Inserting the table into MotherDuck
Now that the data has been loaded into a dataframe object, we can connect to MotherDuck and insert the table.
:::note
You will need to [generate a token](/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/#creating-an-access-token) in your MotherDuck account. For production use cases, make sure to use a secret manager and never commit your token to your codebase.
:::
```py
import duckdb
motherduck_token = 'your_token'
# Attach using the MOTHERDUCK_TOKEN
duckdb.sql(f"ATTACH 'md:my_db?MOTHERDUCK_TOKEN={motherduck_token}'")
# Create or replace table in the attached database
duckdb.sql(
"""
CREATE OR REPLACE TABLE my_db.main.BillOfMaterials AS
SELECT * FROM df
"""
)
```
This will create the table, or replace it for the table already exists.
## Handling More Complex Workflows
Production use cases tend to be much more complex and include things like incremental builds & state management. In those scenarios, please take a look at our [ingestion partners](https://motherduck.com/ecosystem/?category=Ingestion), which includes many options including some that offer native python. An overview of the MotherDuck Ecosystem is shown below.

---
Source: https://motherduck.com/docs/key-tasks/data-warehousing/replication/flat-files
# Replicating flat files to MotherDuck
> Load CSV, Parquet, and JSON files into MotherDuck from local storage or cloud sources.
The goal of this guide is to show users simple examples of loading data from flat file sources into MotherDuck. Examples are shown for both the MotherDuck Web UI and the DuckDB CLI. To install the DuckDB CLI, [check out the instructions first.](/getting-started/interfaces/connect-query-from-duckdb-cli)
## CSV
### MotherDuck UI
From the UI, follow these steps:
1. Navigate to the **Add Data** section.
2. Select the file. This file will be uploaded into your browser so that it can be queried by DuckDB.
3. Execute the generated query which will create a table for you.
1. Modify the query as needed to suit the correct Database / Schema / Table name.
### DuckDB CLI
In the CLI, you can load a CSV file using the `read_csv` function. For example:
### Local file
```sql
CREATE TABLE my_table AS
SELECT * FROM read_csv('path/to/local_file.csv');
```
### S3 file
To load from S3, ensure your DuckDB instance is configured with [S3 secrets](/documentation/integrations/cloud-storage/amazon-s3.mdx). Then:
```sql
CREATE TABLE my_table AS
SELECT * FROM read_csv('s3://bucket-name/path-to-file.csv');
```
## JSON
### MotherDuck UI
From the UI, follow these steps:
1. Navigate to the **Add Data** section.
2. Select the file. This file will be uploaded into your browser so that it can be queried by DuckDB.
3. Execute the generated query which will create a table for you.
1. Modify the query as needed to suit the correct Database / Schema / Table name.
### DuckDB CLI
In the CLI, use the `read_json` function to load JSON files.
### Local file
```sql
CREATE TABLE my_table AS
SELECT * FROM read_json('path/to/local_file.json');
```
### S3 file
Make sure S3 support is enabled as described in the [S3 secrets documentation](/documentation/integrations/cloud-storage/amazon-s3.mdx).
```sql
CREATE TABLE my_table AS
SELECT * FROM read_json('s3://bucket-name/path-to-file.json');
```
:::tip[Provide a schema for large or deeply nested JSON]
When loading large JSON files, DuckDB scans the data to discover the schema during query planning. For deeply nested or complex JSON, this can add significant time.
To speed things up, provide the schema directly with the `columns` parameter:
```sql
CREATE TABLE my_table AS
SELECT * FROM read_json(
'path/to/local_file.json',
columns={
id: 'BIGINT',
name: 'VARCHAR',
amount: 'DECIMAL(10,2)'
}
);
```
If you already have a table with the right schema, use `INSERT INTO` instead of `CREATE TABLE AS` — DuckDB skips schema discovery when the target schema is known:
```sql
INSERT INTO my_table
SELECT * FROM read_json('path/to/local_file.json');
```
You can also limit how deep DuckDB looks into nested structures with `maximum_depth`, or reduce the number of sampled objects with `sample_size` (default: 20480). See the [DuckDB JSON documentation](https://duckdb.org/docs/stable/data/json/loading_json) for all available options.
:::
## Parquet
### MotherDuck UI
From the UI, follow these steps:
1. Navigate to the **Add Data** section.
2. Select the file. This file will be uploaded into your browser so that it can be queried by DuckDB.
3. Execute the generated query which will create a table for you.
1. Modify the query as needed to suit the correct Database / Schema / Table name.
### DuckDB CLI
In the CLI, use the `read_parquet` function to load Parquet files.
### Local file
```sql
CREATE TABLE my_table AS
SELECT * FROM read_parquet('path/to/local_file.parquet');
```
### S3 file
Ensure S3 support is enabled as described in the [S3 secrets documentation](/documentation/integrations/cloud-storage/amazon-s3.mdx).
```sql
CREATE TABLE my_table AS
SELECT * FROM read_parquet('s3://bucket-name/path-to-file.parquet');
```
## Handling more complex workflows
Production use cases tend to be much more complex and include things like incremental builds & state management. In those scenarios, please take a look at our [ingestion partners](https://motherduck.com/ecosystem/?category=Ingestion), which includes many options including some that offer native python. An overview of the MotherDuck Ecosystem is shown below.

---
Source: https://motherduck.com/docs/key-tasks/data-warehousing/replication/spreadsheets
# Using Excel and Google Sheets data in MotherDuck
> Load Excel and Google Sheets data into MotherDuck using the DuckDB CLI or HTTPS CSV export URLs.
Key bits of data and side schedules often exist in spreadsheets like Excel and Google Sheets. It is useful to add that data to your data warehouse and query it. This guide shows how to perform this workflow using the DuckDB CLI for both [Excel](#microsoft-excel) and [Google Sheets](#google-sheets).
:::tip
To use these extensions, you will need to first install the DuckDB CLI. [Instructions can be found here.](/getting-started/interfaces/connect-query-from-duckdb-cli).
:::
## Microsoft Excel
:::note
The purpose of this guide is to show you how to _load_ data from Excel into MotherDuck. If you'd like to _retrieve_ MotherDuck data in Excel, you can [follow this guide](/integrations/bi-tools/excel/).
:::
To read from an Excel spreadsheet, open the DuckDB CLI by typing `duckdb 'md:'` in your terminal.
This will ask you for access to your MotherDuck account if you haven't already provided it.
You can read Excel files directly with `SELECT * FROM 'movies.xlsx'`, which will automatically load the
DuckDB Excel extension. If you want to get more control you can use
[the `read_xlsx` function](https://duckdb.org/docs/stable/core_extensions/excel) directly.
```sql
SELECT * FROM read_xlsx('movies.xlsx', sheet = 'Action Movies');
```
The previous query returns the data set to the terminal, but the query can be modified to write the data into MotherDuck with "Create Table As Select" (CTAS).
```sql
CREATE OR REPLACE TABLE my_db.main.my_movies AS -- use fully qualified table name
SELECT *
FROM 'C:\users\documents\movies.xlsx';
```
Sometimes there is data in multiple tabs. In that case, you can use the `sheet` parameter to pass the tab names, and depending on the context, even union multiple tabs into a single table.
```sql
CREATE OR REPLACE TABLE my_db.main.my_movies AS -- use fully qualified table name
SELECT *
FROM read_xlsx('C:\users\documents\movies.xlsx', sheet = 'Action Movies')
UNION ALL
SELECT *
FROM read_xlsx('C:\users\documents\movies.xlsx', sheet = 'Romance Movies');
```
## Google Sheets
### Query Google Sheets as CSV over HTTPS
If a Google Sheet is publicly accessible, or can be accessed with HTTP authentication, query it from MotherDuck with DuckDB's `read_csv()` function and the Google Sheets CSV export URL:
```sql
SELECT *
FROM read_csv(
'https://docs.google.com/spreadsheets/d//export?format=csv&gid=',
MD_RUN = REMOTE
);
```
The `sheet_id` is the value between `/d/` and `/edit` in the Google Sheet URL. The `gid` identifies the worksheet tab. When you run this while connected to MotherDuck, the HTTPS read can execute server side in MotherDuck.
To keep the spreadsheet queryable as live source data, create a view:
```sql
CREATE OR REPLACE VIEW my_db.main.sheet_source AS
SELECT *
FROM read_csv(
'https://docs.google.com/spreadsheets/d//export?format=csv&gid=',
MD_RUN = REMOTE
);
```
To snapshot the current spreadsheet data into MotherDuck, create a table instead:
```sql
CREATE OR REPLACE TABLE my_db.main.sheet_snapshot AS
SELECT *
FROM read_csv(
'https://docs.google.com/spreadsheets/d//export?format=csv&gid=',
MD_RUN = REMOTE
);
```
For private sheets, create an HTTP secret with an OAuth bearer token and scope it to Google Sheets:
```sql
CREATE SECRET google_sheets_http IN MOTHERDUCK (
TYPE HTTP,
SCOPE 'https://docs.google.com',
EXTRA_HTTP_HEADERS MAP {
'Authorization': 'Bearer '
}
);
```
See the [DuckDB HTTP authentication documentation](https://duckdb.org/docs/current/core_extensions/httpfs/https#authenticating) for more `httpfs` authentication options. For more detail on this Google Sheets URL pattern, see [Swimming in Google Sheets with MotherDuck](https://motherduck.com/blog/google-sheets-motherduck/).
### Query with the Google Sheets extension
::::info
While the Excel extension is a core DuckDB extension, the Google Sheets extension is a community extension maintained by Evidence.
::::
The first step to handle Google Sheets is to install the [duckdb-gsheets](https://duckdb-gsheets.com/) extension. That is done with these commands after starting the DuckDB CLI with `duckdb 'md:'`
```sql
INSTALL gsheets FROM community;
LOAD gsheets;
```
Since Google Sheets is a hosted application, we need to use [DuckDB Secrets](https://duckdb.org/docs/configuration/secrets_manager.html)
to handle authentication. This is as simple as:
```sql
CREATE SECRET (TYPE gsheet);
```
:::note
Using this workflow will require interactivity with a browser, so if you need to run it from a job (i.e. Airflow or similar), consider setting up a [Google API access token](https://duckdb-gsheets.com/#getting-a-google-api-access-token).
:::
To read from a Google Sheet, we need at minimum the sheet id, which is found in the URL, for example `https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit`. The string between `d/` and `/edit` represents the spreadsheet id. It can therefore be queried with:
```sql
SELECT *
FROM read_gsheet('https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit');
```
The previous query returns the data set to the terminal, but the query can be modified to write the data into MotherDuck with "Create Table As Select" (CTAS).
```sql
CREATE OR REPLACE TABLE my_db.main.my_table AS -- use fully qualified table name
SELECT *
FROM read_gsheet('https://docs.google.com/spreadsheets/d/11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8/edit');
```
For convenience, the spreadsheet id itself can be queried as well.
```sql
SELECT *
FROM read_gsheet('11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8');
```
To query data from multiple tabs, the tab name can be passed as parameter using `sheet` to select the preferred tab.
```sql
SELECT * FROM read_gsheet('11QdEasMWbETbFVxry-SsD8jVcdYIT1zBQszcF84MdE8', sheet='Sheet2');
```
For more detailed documentation, including writing to Google Sheets, review the [duckdb-gsheets documentation](https://duckdb-gsheets.com/#getting-a-google-api-access-token).
## Handling more complex workflows
Production use cases tend to be much more complex and include things like incremental builds & state management. In those scenarios, please take a look at our [ingestion partners](https://motherduck.com/ecosystem/?category=Ingestion), which includes many options including some that offer native python. An overview of the MotherDuck Ecosystem is shown below.

---
## 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=%2Fkey-tasks%2Fdata-warehousing%2Freplication%2F&page_title=MotherDuck%20Documentation%20-%20Replication&text=
```
Optionally append `&source=` such as `claude.ai` or `chatgpt`.
`page_path` and `text` are required; `page_title` and `source` are optional. Responses: `200 {"feedback_id": ""}`, `400` for malformed query parameters, and `429` when rate-limited.