How to convert an excel product catalogue to mysql insert for woocommerce
- Step 1Open the generator — The Excel → SQL entry redirects to the JSON to SQL converter — the live engine — which accepts
.xlsx,.xls,.ods,.csv,.jsonand reads the first sheet of your product workbook. - Step 2Lay out the product sheet — Put the catalogue on the first sheet with a header row (
sku,name,price,stock,featured, ...). Flatten any pricing formulas first with formula-to-value so the INSERTs carry final numbers, not=B2*1.2. - Step 3Set the table name — Type your target table (e.g.
wp_wc_product_stagingor a customproductstable). Use a staging/custom table — this generates flat INSERTs, not the multi-tablewp_posts/wp_postmetastructure WooCommerce uses internally. - Step 4Select MySQL — Click the MySQL dialect button for backtick identifiers,
1/0booleans (TINYINT(1)columns), andINSERT IGNOREconflict syntax. - Step 5Enable INSERT IGNORE and trim columns — Tick ON CONFLICT DO NOTHING (renders as
INSERT IGNOREon MySQL) for re-runnable loads, keep CREATE TABLE + IF NOT EXISTS on for a self-contained file, and list spreadsheet-only fields (supplier_notes,margin) in Exclude columns. - Step 6Generate and load — Click Generate SQL, then Copy into phpMyAdmin's SQL tab or Download SQL to run with the
mysqlCLI / Workbench against staging. Verify withSELECT COUNT(*)before promoting.
MySQL output for a product catalogue
What the MySQL dialect produces, mapped to typical product columns. Pricing precision and serialized WooCommerce meta need manual attention (see notes).
| Product column | Cell type | Generated MySQL |
|---|---|---|
sku | Text | TEXT, quoted value e.g. 'WC-001' |
name | Text (may have apostrophe) | TEXT, 'Joe''s Coffee' |
price | Decimal | REAL — edit to DECIMAL(10,2) for money |
stock | Whole number | INTEGER |
featured | Boolean TRUE/FALSE | TINYINT(1), value 1/0 |
sale_price (blank) | Empty cell | NULL |
WooCommerce reality check
Where flat INSERTs fit WooCommerce and where they don't. The tool is a data loader, not a WooCommerce-schema generator.
| Goal | Fits this tool? | Approach |
|---|---|---|
| Custom/staging products table | Yes | Generate flat INSERTs directly |
| Bulk simple-product import via WooCommerce | Use WC CSV importer | WooCommerce's own importer maps to wp_posts for you |
Direct wp_posts + wp_postmeta seed | Partial | Generate per-table INSERTs; you map columns to the WP schema yourself |
Serialized meta (_product_attributes) | No | PHP-serialized values must be built outside this tool |
| Term/category relationships | No | wp_term_relationships linking is not generated |
Cookbook
Product-catalogue fragments in MySQL dialect. Defaults shown: MySQL, CREATE TABLE on, IF NOT EXISTS on; INSERT IGNORE where noted.
Flat product staging table
A simple catalogue sheet becomes a MySQL CREATE TABLE plus a multi-row INSERT with backtick identifiers and a TINYINT(1) featured flag.
Excel (Sheet1):
sku | name | price | featured
WC-001 | Joe's Coffee| 12.50 | TRUE
WC-002 | Tea Tin | 8.00 | FALSE
Generated MySQL (table 'products'):
CREATE TABLE IF NOT EXISTS `products` (
`sku` TEXT,
`name` TEXT,
`price` REAL,
`featured` TINYINT(1)
);
INSERT INTO `products` (`sku`, `name`, `price`, `featured`)
VALUES
('WC-001', 'Joe''s Coffee', 12.5, 1),
('WC-002', 'Tea Tin', 8, 0);Re-runnable load with INSERT IGNORE
The ON CONFLICT toggle renders as INSERT IGNORE in MySQL, so re-running the catalogue skips SKUs already present instead of erroring (requires a unique key on sku).
Options: MySQL, ON CONFLICT DO NOTHING
INSERT IGNORE INTO `products` (`sku`, `name`)
VALUES
('WC-001', 'Joe''s Coffee'),
('WC-002', 'Tea Tin');
-- second run: existing SKUs skipped, no errorFix price columns to DECIMAL
Decimals infer REAL (floating point), which can drift on money. Hand-edit the DDL to DECIMAL(10,2) before loading prices.
Generated: `price` REAL Edit before running (money-safe): `price` DECIMAL(10,2) -- 12.50 then stores exactly, not 12.4999...
Drop supplier-only columns
Catalogue sheets often carry margin/supplier notes you don't want in the products table. Exclude them.
Exclude columns: margin, supplier_notes, cost Result: only customer-facing columns (sku, name, price, stock, featured) appear in the CREATE TABLE and INSERTs.
Mapping toward wp_posts (manual)
If you must seed WordPress tables directly, name your sheet columns to match wp_posts and set the table name accordingly — but you own the column mapping; this is not automatic.
Sheet headers renamed to WP schema: post_title | post_status | post_type Joe's Coffee | publish | product Table name: wp_posts → generates INSERT INTO `wp_posts` (`post_title`, ...) You still handle wp_postmeta + term links separately.
Edge cases and what actually happens
Expecting a turnkey WooCommerce import
Schema mismatchWooCommerce products live across wp_posts + wp_postmeta with serialized meta and term relationships. This tool generates flat INSERTs from your columns — great for a staging/custom table, not a one-click wp_posts seeder. For standard imports, WooCommerce's own CSV importer maps to the WP schema for you.
Price stored as REAL drifts
Precision riskDecimal prices infer REAL (floating point). 12.50 can store as 12.4999.... Edit the DDL to DECIMAL(10,2) before loading money columns, or store prices as integer cents.
Serialized meta needed
Not supportedWordPress meta like _product_attributes is PHP-serialized. The tool only emits scalar values; it cannot build serialized arrays. Construct those in PHP/WP-CLI, not here.
SKU with apostrophe or quotes
Escaped, supportedProduct names like Men's Shoes are escaped by doubling the quote ('Men''s Shoes'), valid in MySQL. No manual cleanup needed for apostrophes.
INSERT IGNORE without a unique key
No-op skipINSERT IGNORE only skips rows that violate a unique/primary key. If the staging table has no unique key on sku, every row inserts (and duplicates accumulate). Add a UNIQUE(sku) constraint for the skip to work.
Date columns (created/modified) as serials
By designExcel dates infer INTEGER. WordPress expects datetime strings. Standardise the column to ISO text with the date standardizer first; MySQL accepts '2024-01-01 00:00:00'-style strings into datetime columns.
Multi-sheet catalogue (variations on tab 2)
First sheet onlyOnly the first sheet is read. Product variations on a second tab are ignored. Generate each sheet separately, or combine with the sheet joiner first.
Large catalogue over the row cap
Upgrade requiredCode generation caps at 100 rows (Free), 1,000 (Pro), 10,000 (Pro+Media), unlimited (Developer). A 30,000-SKU catalogue is truncated below Developer; for very large loads, consider WooCommerce's CSV importer or a LOAD DATA into staging.
Leading-zero SKUs lose their zeros
Format as TextA SKU like 00123 in a number-formatted cell becomes 123. Format the SKU column as Text in Excel so it's read as a string and emitted as '00123'.
Frequently asked questions
Does this directly import products into WooCommerce?
Not into WooCommerce's native schema automatically. It generates flat MySQL INSERTs from your sheet columns — ideal for a staging/custom table. WooCommerce stores products across wp_posts + wp_postmeta with serialized meta, which you'd map manually. For standard imports, use WooCommerce's own CSV importer.
Why MySQL dialect for WooCommerce?
WordPress/WooCommerce runs on MySQL (or MariaDB). The MySQL dialect gives backtick identifiers, 1/0 booleans as TINYINT(1), and INSERT IGNORE — all matching the WordPress conventions.
How do I avoid duplicate SKUs on re-run?
Tick ON CONFLICT DO NOTHING, which renders as INSERT IGNORE in MySQL, so existing SKUs are skipped. This requires a UNIQUE key on the SKU column — without it, INSERT IGNORE won't skip anything.
Are product names with apostrophes safe?
Yes — single quotes are doubled (Joe's → 'Joe''s'), which is valid MySQL escaping. Apostrophes won't break the INSERT.
How should I handle prices?
Decimal prices infer REAL (floating point), which can round. Edit the generated DDL to DECIMAL(10,2) for money, or store integer cents. Flatten pricing formulas to values first with formula-to-value.
What about leading-zero SKUs?
Format the SKU column as Text in Excel before generating, so 00123 is read as a string and emitted as '00123' rather than the number 123.
Can I generate serialized WooCommerce meta?
No — _product_attributes and similar are PHP-serialized arrays the tool can't build. It emits scalar values only. Construct serialized meta in PHP or WP-CLI separately.
How large a catalogue can I load?
The code-gen quota caps rows at 100 (Free), 1,000 (Pro), 10,000 (Pro+Media), unlimited (Developer); the Excel file ceiling runs 5 MB to 500 MB. For tens of thousands of SKUs, WooCommerce's CSV importer or a LOAD DATA may suit better.
Will product variations on another tab be included?
No — only the first sheet is read. Put variations on the first sheet in a separate run, or join the sheets first.
How do I handle created/modified dates?
Excel dates infer INTEGER. Standardise them to ISO text with the date standardizer first; MySQL then accepts the 'YYYY-MM-DD HH:MM:SS' strings into datetime columns.
Is my catalogue data uploaded?
No. SheetJS parses the workbook in your browser and the SQL is built locally — pricing, supplier, and product data never leave your machine. Only an anonymous run counter is recorded, which you can opt out of.
What if I want to seed via a script instead?
Use Excel → Python to emit rows you can insert via an ORM/WP-CLI script, or the Tailwind table export for a preview. For JSON product feeds, the same engine is the JSON to SQL converter.
Privacy first
Every JAD Excel tool runs entirely in your browser using SheetJS and ExcelJS. Your spreadsheets, formulas, and data never leave your device — verified by zero outbound network requests during processing.