Ah, thanks; I hadn't quite stopped to think about the difference between information available to the shell and what the core library can discover so easily. Still, however, I don't think the docs explains (to my level of understanding) what happened. I think it all depends what mechanism the shell is using to communicate the tuples to the database layer and telling it what to do with it. As I haven't studied the source, and am not at all familiar with the C API, I really can't know. Unfortunately, my csv files come from spreadsheets not of my making, so the column headers won't match. But your response (and the other followup) got a handful of my brain cells working again, so I found a better way, demonstrated here with my toy example. I start `sqlite3` with no argument, thus working at first with the in-memory database, then: ``` ▶▶▶ .shell cat n.csv "fee fie foe foo",bar 1,2 3,4 ▶▶▶ .import -csv n.csv tmpn ▶▶▶ attach 'n.db' as n; ▶▶▶ .schema n CREATE TABLE n.n(a,b,c as (a+b) stored); ▶▶▶ insert into n.n select * from tmpn; ▶▶▶ select * from n; a b c - - - 1 2 3 3 4 7 ``` This seems to me the easiest approach, as the critical parts (`.import`, `attach`, `insert`) are the same no matter the particulars of the database schema and the details of the csv file, so long as the number of columns matches.