Getting MySQL data into Google Sheets

There's no official Google connector for MySQL, which is why every answer you find involves a script, an add-on, or a manual export. Here's what each one actually costs you.

The part everyone underestimates

Getting the data across once is easy. Run the query, export CSV, import. The problem is the second time, and the twentieth: manual exports drift, someone edits the query, and the definition of "revenue" quietly changes between two versions of the same report.

Automating it means letting Google reach your database. Apps Script's JDBC service can connect to MySQL, but your server has to accept connections from Google's published IP ranges — which for most people means opening a production database to a broad slice of the internet, protected by a password. It works. It's also the single riskiest line in most small-company infrastructure.

And whichever route you pick, the refresh runs against a server that's doing real work. A dashboard that refreshes every fifteen minutes is a query every fifteen minutes, forever, competing with whatever your application is doing.

Three ways to get there

All three work. They differ in what you expose, what you maintain, and what the refresh costs your production server.

Apps Script and JDBC

A script bound to the sheet opens a JDBC connection to MySQL and writes query results into a tab on a time trigger.

  • Free, automatic, and entirely under your control
  • Arbitrary SQL — the sheet gets exactly the shape you want
  • Requires allowing Google's IP ranges into your database
  • Script quotas and timeouts on large result sets
  • It's code in a spreadsheet: undocumented, unversioned, and owned by whoever wrote it

A marketplace add-on

A third-party Sheets add-on that stores your credentials and refreshes queries on a schedule.

  • No code to write
  • Scheduling and multiple queries out of the box
  • A third party holds credentials to your database
  • Per-seat or per-refresh pricing
  • Still connecting to production, just with someone else's connector

Query a PostgreSQL copy, publish the answer

BeQuery

BeQuery maintains an isolated, verified PostgreSQL copy of the MySQL database. You query the copy and export a result that's already the answer.

  • Nothing needs to reach your production database — the copy is what gets queried
  • MySQL type quirks are handled in the clone: zero-dates and unsigned ints don't break the export
  • Row counts verified against the source on every sync, so the copy isn't quietly incomplete
  • Saved queries keep a metric's definition stable over time
  • The sheet pulls from us rather than being written to, and refreshes on Sheets' own schedule
  • Scheduled sync rather than live, so the copy lags by your sync interval

The path that stays usable, step by step

  1. 1

    Connect your store to BeQuery

    Read-only MySQL credentials, host and port. BeQuery clones the database into an isolated PostgreSQL copy that only your team can reach — the shop itself is only ever read.

  2. 2

    Write the question as a query, not an export

    This is the step that decides whether the spreadsheet survives. In the SQL editor, aggregate first: revenue by month, margin by product, customers by cohort. You want the answer, which is hundreds of rows, not the raw orders table, which is hundreds of thousands.

  3. 3

    Publish it as a link, or export it once

    Save the query, then either export CSV or XLSX from the editor for a one-off, or publish the query as a CSV link. XLSX exports are capped at 500,000 rows; CSV will happily hand you more than a spreadsheet can hold, which is another reason to aggregate first.

  4. 4

    Paste the formula and let Sheets refresh it

    Drop =IMPORTDATA("…your link…") into a cell. Sheets fetches it on its own — roughly once an hour — so the tab stays current without anyone exporting anything again. Build your charts and pivots on top of that range. The link is a password in URL form: anyone who can see the formula can read the results, and you can revoke it from BeQuery at any time.

Is a spreadsheet the right home for this?

Sheets is a superb interface for thinking and a poor one for storage. The line between the two is where this decision lives.

Yes — Sheets earns its place

  • The output is genuinely a spreadsheet — models, scenarios, manual columns alongside the data
  • A handful of people need to poke at the numbers without learning SQL
  • The result set is small: an aggregate, a summary, a list you can read

You've outgrown it — use a dashboard instead

  • You're pulling tens of thousands of raw rows and aggregating in the sheet
  • The same refresh happens on a schedule and nobody edits the output by hand
  • You've started maintaining a script whose failure mode is a silently stale tab

Common questions

Can Apps Script connect to PostgreSQL instead?

No — the JDBC service supports MySQL, Microsoft SQL Server and Oracle, and PostgreSQL isn't on the list. It's worth knowing before you plan around it: for a PostgreSQL copy, the routes into Google's tools are a CSV link the sheet pulls with IMPORTDATA, a manual export from the SQL editor, or Looker Studio reading it with the native PostgreSQL connector.

Can a sheet refresh itself, or is this manual every time?

It can refresh itself. Publish a saved query as a CSV link, paste =IMPORTDATA("…") into a cell, and Sheets refetches it on its own — about once an hour. Worth being precise about the direction: BeQuery doesn't write into your spreadsheet, the spreadsheet pulls from BeQuery. Nothing is pushed, nothing is stored in Google on our side, and revoking the link stops it immediately.

How safe is that link?

Treat it as a password. It's fetched anonymously by Google, so the URL itself is the credential — anyone holding it, including anyone who can open your spreadsheet and read the formula, can see that query's results. It's deliberately narrow: one saved query, read-only, row-capped, and revocable. We store only a hash of it, which is why it's shown once when you create it and can't be retrieved afterwards. For anything sensitive shared widely, use Looker Studio on a read-only connection instead.

Why not connect Sheets straight to my shop's database?

Google Apps Script can open a JDBC connection to MySQL, so it is technically possible. It means exposing your production database to Google's IP ranges, writing and maintaining the script, and having every refresh query the same server that serves your customers. It's a lot of moving parts to end up with a spreadsheet that occasionally times out.

How much data can a spreadsheet actually hold?

Google Sheets caps a spreadsheet at 10 million cells across all its tabs. That sounds enormous until you divide by columns: a 20-column export runs out at around 500,000 rows, and performance gets unpleasant well before the hard limit. Aggregated results are never a problem; raw order lines from a busy store are.

See it on your own store first

Free tier, no credit card, read-only access. Production is never written to — and you can explore the demo store before connecting anything.