How to Query a CSV File with SQL in the Browser
To query a CSV file with SQL in the browser, open Query CSV with SQL, upload the file, and run SELECT statements against the table it creates. The table is named after the file (orders.csv becomes orders_csv), spaces and punctuation in headers become underscores, and every column is stored as TEXT. Cast numeric columns before you compare, sort or sum them.
The tool loads the CSV into SQLite 3.39.3 (sql.js) in your browser. The file is read and queried locally. Every output below was produced by that engine from the sample file.
Sample file
Download orders.csv or save this text under that name. The headers contain spaces, order 1004 has an apostrophe in the name, and order 1006 has an empty Total:
Order ID,Customer Name,Region,Order Date,Total
1001,Ana Lopez,West,2026-10-01,25.00
1002,Ben Ito,East,2026-10-02,120.50
1003,Chloe Park,West,2026-10-03,9.99
1004,Dev O'Neil,East,2026-10-05,100
1005,Ana Lopez,West,2026-10-07,250.00
1006,Eli Brown,North,2026-10-08,
Keep the file name orders.csv so the table name matches the queries below.
Load the CSV and check the table
- Open Query CSV with SQL and click Upload.
- Choose
orders.csv. The tool creates and fills the table, then opens the SQL editor. - Check the generated column names and types:
SELECT name, type FROM pragma_table_info('orders_csv');
name | type
--------------|-----
Order_ID | TEXT
Customer_Name | TEXT
Region | TEXT
Order_Date | TEXT
Total | TEXT
The tool builds this from the file. It does not infer types:
CREATE TABLE IF NOT EXISTS orders_csv (Order_ID TEXT, Customer_Name TEXT, Region TEXT, Order_Date TEXT, Total TEXT);
Header names are rewritten by replacing every character outside A-Z, a-z, 0-9 and _ with _. So Order ID becomes Order_ID, and a header like Total ($) becomes Total____. Use the rewritten names in your queries.
Filter rows
Text comparisons work as you would expect. ISO dates (YYYY-MM-DD) also compare correctly as text, because their character order matches date order:
SELECT Order_ID, Customer_Name, Total
FROM orders_csv
WHERE Region = 'West'
AND Order_Date >= '2026-10-03';
Order_ID | Customer_Name | Total
---------|---------------|-------
1003 | Chloe Park | 9.99
1005 | Ana Lopez | 250.00
Open this query (upload orders.csv when the page asks for a file).
Numbers are compared as text
Because Total is a TEXT column, SQLite compares Total > 100 as text, character by character. The result looks plausible but is wrong. It includes 25.00 and 9.99, because "2" and "9" sort after "1":
SELECT Order_ID, Total FROM orders_csv WHERE Total > 100;
Order_ID | Total
---------|-------
1001 | 25.00
1002 | 120.50
1003 | 9.99
1005 | 250.00
Cast the column to a number before comparing:
SELECT Order_ID, Total
FROM orders_csv
WHERE CAST(Total AS REAL) > 100;
Order_ID | Total
---------|-------
1002 | 120.50
1005 | 250.00
Group and aggregate
Empty CSV cells are imported as empty strings '', not NULL. Use NULLIF(Total, '') to turn them into NULL, so that COUNT skips them and the sum is NULL when a group has no values:
SELECT Region,
COUNT(*) AS orders,
COUNT(NULLIF(Total, '')) AS priced,
ROUND(SUM(CAST(NULLIF(Total, '') AS REAL)), 2) AS revenue
FROM orders_csv
GROUP BY Region
ORDER BY revenue DESC;
Region | orders | priced | revenue
-------|--------|--------|--------
West | 3 | 3 | 284.99
East | 2 | 2 | 220.5
North | 1 | 0 | NULL
SUM(Total) without the cast also returns 284.99 and 220.5, because SUM converts text to numbers. But it reports 0 for North, which hides the fact that the order has no total.
Sort
ORDER BY Total DESC on a TEXT column sorts text, so 9.99 comes first:
Order_ID | Total
---------|-------
1003 | 9.99
1005 | 250.00
1001 | 25.00
1002 | 120.50
1004 | 100
1006 | ''
Sort by the cast value instead:
SELECT Order_ID, Customer_Name, Total
FROM orders_csv
ORDER BY CAST(Total AS REAL) DESC
LIMIT 3;
Order_ID | Customer_Name | Total
---------|---------------|-------
1005 | Ana Lopez | 250.00
1002 | Ben Ito | 120.50
1004 | Dev O'Neil | 100
Common errors
-
Double quotes around the original header. In SQLite,
"Order ID"refers to a column only if one has that exact name. Here none does, so SQLite treats it as a text literal andSELECT "Order ID" FROM orders_csvreturns the stringOrder IDon every row instead of an error. UseOrder_ID. -
no such table: orders. The table name comes from the whole file name, including the extension:orders.csvbecomesorders_csv. To list the actual table names, run:SELECT name FROM sqlite_master WHERE type = 'table'; -
Apostrophes in your query. Values such as
Dev O'Neilimport as-is. In a SQL string literal, write the apostrophe twice:WHERE Customer_Name = 'Dev O''Neil'.
Query vs CSV to SQL
Query CSV with SQL runs your SELECT statements against the file in your browser. CSV to SQL uses the same conversion, with TEXT columns, to generate CREATE TABLE and INSERT statements that you copy into another database. The Turn a spreadsheet into SQL recipe covers that workflow. For typed columns and analytical SQL over larger files, use the DuckDB playground.