SQLite Forum

sqlite bindings error
Login

sqlite bindings error

(1) By anonymous on 2021-02-10 19:01:39 [link]

# (API Call Happens and Works)#
r = requests.get(url, params=data) #<-- This is CSV

btc_price_rows = r.text <-- I can print this and see the correct data 

# connect to db, create tables and insert #
c.execute("CREATE TABLE IF NOT EXISTS btc_price_table (btc_price_timestamp TEXT, btc_price_value REAL)")

values = (btc_price_rows,)

c.executemany("INSERT OR REPLACE INTO btc_price_table VALUES (?, ?)", (values,)) <-- I think this is the problem but not sure why 

# I get this error # 
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 2, and there are 19931624 supplied.

My best guess here is that it has something to do with r and btc_price_rows are being presented to sqlite, I guess it's confused about columns vs data, it thinks every row of data is a unique column value? Hence the expecting 2 got 19931624 error? 

if I print the data out it looks like this, just two columns, time and value. 

2021-02-10T18:40:00Z,45016.18724409042

I read that ISO8601 RFC3339 is the time format which I believe sqlite wants it defined as datatype TEXT. 

Appreciate any help on figuring this out.

(2.3) By Keith Medcalf (kmedcalf) on 2021-02-10 19:42:02 edited from 2.2 in reply to 1 [link]

That is only one value that is a text string that contains an embedded ",".  

What you think are "multiple rows" are really just "\\n" separated text.

The content of *btc_price_rows* is not rows of fields.  It is one big text field that you need to parse into a list of tuples.  .executemany requires a sequence of sequences/dictionaries as the second parameter.  That is, each member of the outer sequence is used as the binding for the statement.  That is:

```
c.executemany(SQL, bindings)
```

is semantically equivalent to

```
for onebinding in bindings:
    c.execute(SQL, onebinding)
```

without the overhead of re-preparing the SQL for each iteration.

You probably want something like this:

```
btc_price_rows = []
for line in requests.get(url, params=data).text:
  btc_price_rows.append(tuple(line.strip('\r\n').split(',')))
c.executemany("INSERT OR REPLACE INTO btc_price_table VALUES (?, ?)", btc_price_rows)
```

(3) By David Raymond (dvdraymond) on 2021-02-10 20:14:10 in reply to 1

See Keith's response.

But also, are you sure you copied and pasted everything correctly? I swear this should complain about only having 1 supplied.

.executemany(sql, (values,))

should basically run .execute(sql, values) once, since (values,) is a 1 element tuple.

And "values = (btc_price_rows,)" means values itself is also a 1 element tuple.
So shouldn't it complain about only having 1 binding supplied?

I would bet 19931624 is the size of r.text, and you did either

.executemany(sql, (btc_price_rows,))

or you did values = btc_price_rows

or something similar.