tuliq
Runs in your browser

CSV to SQLite Query Engine

Loads one or more CSV files into a real, in-browser SQLite database (via sql.js, SQLite compiled to WebAssembly) and lets you query them with actual SQL โ€” WHERE, GROUP BY, aggregate functions, and JOINs across multiple files, not a spreadsheet-style column filter. Each uploaded file becomes its own table named after the file, so joining two related CSVs is as simple as writing the JOIN. Numeric columns are only treated as numeric if every value actually parses as one, so comparisons and sorts work as numbers, not text; a blank cell becomes real SQL NULL, not an empty string. The database lives entirely in your browser's memory โ€” nothing is uploaded, and nothing persists once you leave the page.

Each file becomes its own table โ€” load more than one to JOIN across them.

About this tool

Loads one or more CSV files into a real, in-browser SQLite database (via sql.js, SQLite compiled to WebAssembly) and lets you query them with actual SQL โ€” not a spreadsheet-style column filter, the real thing: WHERE, GROUP BY, aggregate functions, and JOINs across multiple files. Each uploaded file becomes its own table, named after the file (sanitized to a valid SQL identifier), which is what makes joining two related CSVs โ€” an orders file and a customers file, say โ€” as simple as writing the JOIN yourself. Column types aren't guessed loosely: a column is only treated as numeric if every value in it actually parses as a number (the same rule tuliq's chart tools use), so a WHERE or ORDER BY on a numeric column compares as numbers, not as text โ€” the classic spreadsheet-tool bug where "10" sorts before "9". A blank cell becomes real SQL NULL, not an empty string or a silent zero, so COUNT, AVG, and IS NULL all behave the way they would against a real database. The whole database exists only in your browser's memory for as long as the tab is open โ€” there's no server, no persistence, and no upload at any point.

What you can do

  • Real SQLite, compiled to WebAssembly โ€” full SQL, not a spreadsheet-style filter
  • Load multiple CSVs at once โ€” each becomes its own table you can JOIN across
  • Numeric columns are detected automatically, so WHERE and ORDER BY compare as numbers, not text
  • The database lives entirely in your browser's memory โ€” nothing is uploaded, nothing persists after you leave

How to use

Step 1

Load one or more CSVs

Each file becomes its own table, named after the file.

Step 2

Write a SQL query

SELECT, WHERE, GROUP BY, JOIN across tables โ€” anything SQLite supports.

Step 3

Run it

Ctrl+Enter (โŒ˜+Enter on Mac) also runs the query, so you don't need to reach for the mouse.

Example

Loading orders.csv and customers.csv, you could join them directly:

query.sql

SELECT c.name, SUM(o.amount) AS total
FROM "orders" o
JOIN "customers" c ON o.customer_id = c.customer_id
GROUP BY c.name
ORDER BY total DESC;

Table names come from the file name (lowercased, non-identifier characters collapsed to underscores) โ€” "Sales Data.csv" becomes the table "sales_data".

How your data is handled

This tool is labeled ๐ŸŸข Runs in your browser: sql.js runs entirely client-side via WebAssembly, and the database it builds exists only in your browser's memory. Nothing about your files or your queries is ever uploaded, logged, or sent anywhere โ€” closing or refreshing the tab discards the whole database, since none of it is saved to disk.

Frequently asked questions

What SQL features are supported?+

Everything SQLite supports โ€” SELECT, WHERE, GROUP BY, HAVING, ORDER BY, JOINs, subqueries, aggregate functions (SUM, AVG, COUNT, MIN, MAX), and SQLite's own functions. This is real SQLite, not a simplified subset.

Can I query across two different CSV files?+

Yes โ€” load both files (each becomes its own table named after the file) and JOIN them in your query, exactly as you would with two real database tables.

How are column types decided?+

A column is treated as numeric (SQLite REAL) only if every non-empty value in it parses as a number โ€” one stray label anywhere in the column keeps the whole column as TEXT. This matches how tuliq's chart tools decide the same thing, so results stay consistent across tools.

What happens to blank cells?+

They become real SQL NULL, not an empty string or a zero โ€” so COUNT(column), AVG(column), and IS NULL all behave correctly, the way they would against an actual database.

Is my data uploaded anywhere?+

No โ€” sql.js runs entirely in your browser via WebAssembly, and the database it builds lives only in your browser's memory for as long as the tab stays open. Nothing is sent to a server at any point.

Does my database persist if I reload the page?+

No โ€” there's no save/persistence step by design. Reloading or closing the tab discards the database entirely; re-load your CSVs to start again.

Related tools