HOW-TO · DATA SYNC

Get a CSV file into a MySQL table.

By Chris Davidson, founder of yForest · Updated September 26, 2026

MySQL's LOAD DATA INFILE is fast but fussy about file paths, permissions, and the server's own local_infile setting. Mapping the file's columns in QueryFlow sidesteps all three.

Start 14-day free trial Download on theMac App Store

No credit card. 14 days. Cancel in one click.

macOS 15+ · Apple Silicon native · 14-day free trial · No credit card

Quick answer: Add the CSV as a file connection, then build a Data Sync: pick the CSV as source and your MySQL table as target. Map columns, choose Insert, Update or Upsert, and run it, or save it as a recurring job. Pipelines tier.

The permissions fight LOAD DATA INFILE usually starts

LOAD DATA INFILE is the textbook-fast way to get a CSV into MySQL, and it's genuinely worth using when it's available and the file is huge. In practice it often isn't the quick option it looks like: local_infile may be disabled by default on a managed MySQL instance, and depending on how the file's read, the MySQL server process itself, not your local session, may need filesystem access to it. A mapped load through a connection doesn't touch any of that.

Before you start

Steps

  1. Add the file as a connection: click the + next to Databases and pick CSV/Excel.
  2. Open Pipelines → Build and click New Sync.
  3. On the left, pick the file connection as your source.
  4. On the right, pick your MySQL connection and the target table, or create one.
  5. Drag columns across, or click AI Map to pair them by name.
  6. Pick a MODE: Insert for a fresh load, Update or Upsert for a refresh.
  7. For Update or Upsert, set a MATCH ON field that's unique per row.
  8. Click Dry Run, check the preview, then Save or run it now.

A worked example

A customer support platform export needs to refresh a MySQL-backed reporting table nightly:

-- target table
CREATE TABLE IF NOT EXISTS reporting.tickets (
  ticket_id INT PRIMARY KEY,
  status VARCHAR(32),
  assignee VARCHAR(64),
  updated_at DATETIME
);

Map the export's Ticket ID, Status, Assignee and Last Updated columns, set MODE to Upsert, and MATCH ON to ticket_id. A ticket that changed status since yesterday's export updates the existing row instead of duplicating it. Save it as a nightly job matched to when the platform generates its export.

Check it worked

Dry Run shows what would write before anything does. After a real run, compare row counts and check the job's history for type mismatches.

Troubleshooting

If you seeFix
Choose at least one key fieldPick a MATCH ON column for Update or Upsert modes.
Duplicate key values in sourceCheck the export for repeated ticket IDs before syncing.
ZIP code or ID loses leading zerosType the target column as VARCHAR, not numeric.

A note on very large files

For a file in the hundreds of thousands of rows or more, LOAD DATA INFILE, once you clear the permissions hurdle, is still faster in raw throughput than a mapped load. For the recurring exports most teams deal with, a support platform's nightly ticket file, a vendor's weekly catalog, the setup savings of skipping that permissions fight outweigh the throughput difference.

Reusing the mapping for next week's file

If the export's column structure stays the same, point the same file connection at each new export and re-run the sync without rebuilding the mapping. A renamed or reordered column is the actual signal to revisit it.

Character set mismatches worth watching for

A MySQL table created with the older latin1 character set can mangle non-ASCII text, an accented name or a currency symbol, that a modern export assumes is UTF-8. If names or special characters look corrupted after a load, check the target table's character set before assuming the CSV itself is wrong; converting the table to utf8mb4 is usually the actual fix.

Deciding where the imported table lives

A dedicated reporting or staging schema for imported files, rather than mixing them into whatever schema the main application uses, keeps a support platform export's occasional formatting quirks from ever touching production application tables. Downstream reports read from the staging table, and if the export format changes, only that one table needs attention.

Why AI Map earns its keep on a wide export

A support platform export with thirty or forty columns is tedious to map by hand, dragging each field across one at a time, and error-prone in a way that's easy to miss until a downstream report comes up wrong. AI Map pairs columns by name similarity as a starting point, which for a well-named export gets most of the mapping right immediately; the remaining manual work is mostly double-checking the handful of columns whose names genuinely don't match anything obvious on the target side.

A file that arrives with inconsistent row counts

If the same export sometimes has a few hundred rows and other times several thousand with no obvious reason, that's worth investigating at the source rather than assuming Data Sync handled a big file worse than a small one. A platform export that silently truncates under load, or a filter that's inconsistently applied on the vendor's side, produces exactly this symptom, and it shows up first as a row-count anomaly, not an error.

Whether this belongs in a job's file destination instead

If the ultimate goal is just getting the export somewhere a report can read it, and not specifically into a MySQL table joined against other data, a scheduled job with a local file or email destination might be simpler than a Data Sync mapping at all. Data Sync earns its place once the file's data actually needs to live inside MySQL, queried and joined the way any other table would be, rather than just archived or emailed onward.

Setting realistic expectations for how current the table is

A nightly sync against a support platform's nightly export means the MySQL table is always up to a day behind the platform itself, and that's fine for most reporting but worth stating plainly to whoever's building dashboards off it. A report that implies same-day accuracy off a table that's actually a day stale creates confusion that's better prevented with a clear label than explained after the fact.

Keeping the sync resilient to a one-off bad file

An export that arrives corrupted or truncated once, a network hiccup on the platform's end, shouldn't be allowed to silently overwrite a good prior night's data with a partial load. Reviewing the row-synced count in the job's history each morning, even briefly, catches an unusually low number before anyone downstream builds a report on an incomplete table.

What this costs against Fivetran

Fivetran's file connectors meter the same way as any other source under its pricing page (September 26, 2026): 500,000 MAR free, then a $5 base charge per connection between 1 and 1,000,000 MAR, usage above that behind a quote. A nightly ticket export in the low thousands of rows stays inside the free tier regardless, so the real tradeoff here is setup and where the sync runs, not row-based cost.

Sources

Load a CSV into BigQuery MySQL Mac client Every warehouse, one client Integrations Sync Google Sheets to MySQL. Sync PostgreSQL to MySQL.
QueryFlow Studio $9.99/mo · $99/yr
QueryFlow Pipelines $29.99/mo · $199.99/yr

Frequently asked

Why not just use LOAD DATA INFILE?

It's genuinely fast for a trusted local file, but it needs the server's local_infile setting enabled, and depending on the hosting provider, may need the file placed somewhere the MySQL server process itself can read, not just your Mac. Mapping the file through a connection avoids both.

Does the CSV need headers matching the table exactly?

No, you map each column manually or with AI Map. Names don't need to match, only the mapping does.

What if a numeric-looking column has leading zeros, like a ZIP code?

Type that target column as VARCHAR, not a numeric type, or the leading zeros get silently dropped.

Can I schedule this for a file that updates weekly?

Yes, save the sync as a job and set a schedule. Update the file connection first if the file's location changes each time.

Skip the local_infile fight.

14-day free trial, no card. Map it once, run it whenever the file shows up.

Start 14-day free trial

No credit card. 14 days. Cancel in one click.