Load a CSV
Put a file straight into your warehouse with no connector and no schedule. sanda reads the header, types every column and lands the rows in a table.
A CSV upload is the quickest way to get a file into your warehouse: a budget, a price list, a lookup table, an export from a system sanda does not connect to. There is no connector and no schedule. sanda reads the header row, works out a type for each column and lands the rows as a table in your warehouse's raw schema.
Owners, admins and members can load a CSV. Your warehouse has to be ready first. See Provision your warehouse.
Load a file
-
Open the upload page. Go to Data · Connections and press Load a CSV. You can also reach it from the first step of New connection.
-
Choose the file. Drop it on the panel that reads Drop a CSV here, or click to choose, or click to browse. The panel notes what is accepted: Comma, semicolon or tab separated · header row required · up to 8 MB.
-
Name the table. Table name starts as the file's name without its extension. The hint underneath shows where the rows will land, for example Lands as raw.csv__monthly_budget in your warehouse.
-
Say what to do if the table exists. If the table already exists offers Replace it and Append to it. See Replace or append.
-
Choose a destination. If you have more than one warehouse ready, Destination warehouse appears. With one, there is nothing to choose.
-
Press Load it. sanda reads the file, types it and lands the rows. When it finishes, the page reports how many rows landed and lists the columns with their types.
The result page offers Load another file, and Learn from my data, which asks cherry to read the new table and propose what it means for you to accept. See Learn from your data.
What the file has to look like
| Limit | |
|---|---|
| File types | The file chooser offers .csv, .tsv and .txt |
| Size | 8 MB |
| Rows | 250,000 |
| Columns | 250 |
| Header | The first row must name the columns |
| Delimiter | Comma, semicolon or tab. sanda reads it from the header row |
| Encoding | UTF-8 |
A few things that real files do are handled for you. Quoted fields can contain the delimiter, line breaks and doubled quotes. Both Unix and Windows line endings are read. A byte order mark at the start is ignored. Rows shorter than the header are padded with empty cells. Completely blank lines are skipped.
For a file over the limits, use the S3 or SFTP connector, which read files from storage on a schedule.
Column names
sanda cleans every header into a name that is safe to query. It turns letters into lowercase, replaces each run of characters other than a to z and 0 to 9 with one underscore, and trims underscores from the ends. It does not keep the original.
| In the file | Lands as |
|---|---|
Revenue ($) |
revenue |
2024 total |
c_2024_total |
| A blank header | column_5, numbered by its position |
A second date beside the first |
date_2 |
Accented and other non-English letters are replaced too, so Ünïcode becomes n_code. Columns are limited to 58 characters. Rename anything important in the file before you load it.
How types are chosen
sanda reads the whole file, not a sample, and gives each column the strongest type that every value in it supports. One value that does not fit makes the column text, so nothing is ever lost and a late surprise cannot fail a load halfway through.
| If every non-empty value is | The column is |
|---|---|
| A whole number of up to 18 digits | bigint |
| A number, with an optional decimal point or exponent | numeric |
true or false, in any case |
boolean |
A date written 2026-09-30 |
date |
Timestamps such as 2026-09-30 14:30 or 2026-09-30T14:30:00Z, alone or mixed with plain dates |
timestamptz |
| Anything else | text |
Empty cells land as nulls, not as empty strings. A column with nothing in it at all is text.
The rules are strict, so a few common formats stay as text:
- Numbers with thousands separators or currency symbols, such as
1,200or$12.50. - Dates written
30/09/2026or30 Sep 2026. yesandno. A column of1and0becomesbigint, notboolean.
And one goes the other way: a column of values with leading zeros, such as postcodes or account numbers, is read as whole numbers, so 0800 lands as 800. If the zeros matter, put a character in front of every value so the column is read as text, or load the table through an assistant, which can declare a column's type.
If you want a number or a date, write it plainly in the file: 1200, 12.50, 2026-09-30. You can also cast text columns in a view after loading.
Where the table lands
The table is named raw.csv__<name>. sanda builds the name from the Table name you gave it: lowercase, non-alphanumeric characters turned into underscores, a .csv, .tsv or .txt ending removed, and cut at 40 characters. A name that starts with a digit gets t_ in front, so 2026 budget lands as raw.csv__t_2026_budget.
The csv__ prefix keeps hand-loaded tables apart from tables a connection lands, so a CSV can never collide with a sync's table.
Every table gets one extra column of sanda's own, _becca_loaded_at, holding when the row was loaded. Like the other loading columns, it stays out of your semantic fluid. If your file has a column with that name, sanda renames it becca_loaded_at.
A CSV table counts toward your warehouse's storage in the same way a synced table does, and the storage limit applies to it. The load is recorded in Overview · Recent activity as CSV loaded into warehouse.
Replace or append
If the table already exists decides what happens when a table with that name is already there.
- Replace it swaps the table's rows for the file's. The old rows are gone. The whole load is one transaction, so a file that fails to load leaves the existing table as it was.
- Append to it adds the file's rows to what is there. The columns must match the table's: the same names, none missing and none extra. If they do not, nothing loads and the message names the differences, for example These rows don't match raw.csv__budget (new columns region; missing owner). Load with Replace, or use another table name. Append also creates the table when it does not exist yet.
Append casts each value into the type the existing column already has. A value that cannot be cast, such as text in a bigint column, fails the whole load.
Replacing a table that is in use
A table nothing reads yet is dropped and made again in the file's shape. Once something reads it, such as your semantic map or a view of your own under Data · Modelling, sanda keeps the table and replaces its rows in place, so the map and your views go on working.
If the new file's columns differ from the table's:
- A column the file adds goes on the end of the table. The map keeps showing the columns it had, so a new column is in the table but not yet on the map.
- A column the file no longer has comes off the table, and a column whose type changed takes its new type. If the map reads that column, sanda rebuilds the map's view over the new columns for you. Anything on the map built on a column that has gone stops working until you change it.
- A view of your own that reads a column the file drops or retypes stops the load, because sanda never removes your views. Nothing changes, and the message names the view, for example derived.budget_by_region reads owner of raw.csv__budget, and this file leaves that column out or gives it a different type. Keep it as it was, or change that view under Data · Modelling, then load again.
If sanda cannot rebuild the map's view after a replace, the rows still land and the page says so: questions on the table fail until the view is rebuilt. Load the file again, or ask sanda support.
Let an assistant add rows
The checkbox Open it for intake turns the table into a place an assistant can keep adding to. A connected assistant holding the intake permission may then add rows to this table, matching its columns, and do nothing else to it: it cannot replace the table, delete rows or touch any other table. It suits a log someone keeps by talking, such as a daily habit list, a form or a running list of jobs.
Only owners and admins can open a table for intake. If a member ticks the box, the rows still land, and the page says only an owner or admin can open the table. Close a table for intake at any time in the Intake tables panel, under Settings · Integrations. Closing it keeps the rows and stops the assistant adding more.
Someone with the right permission can also land a table, and add to one, by talking to an assistant that is connected to sanda. See Agent tokens and MCP tools.
When a load fails
| Message | What to do |
|---|---|
| The file is empty. | Check you chose the right file |
| The first row must name the columns. | Add a header row |
| There are no data rows under the header. | The file has a header and nothing else |
| That's 300 columns, and uploads cap at 250. | Split the file or drop columns |
| That's 300,000 rows, and uploads cap at 250,000. For bigger drops, use the S3 or SFTP connector. | Use a connector, or split the file |
| Couldn't parse the CSV: a quoted field never closes, so the file may be truncated. | Reopen the file and check it was saved whole |
| This warehouse is at its storage ceiling, so ingest is paused. | Raise the storage limit or clear space. See Usage and suspension |
| derived.… reads … of raw.csv__…, and this file leaves that column out or gives it a different type. | A view of yours reads that column. See Replacing a table that is in use |
| Loading failed: … | The rest of the message says why |
For anything else, see Troubleshoot connections.
Something unclear or out of date? Tell us, and we will fix the page.