Using SQLite3 with Python 2.5, I'm trying to iterate through a list and pull the weight of an item from the database based on the item's name.
I tried using the "?" parameter substitution suggested to prevent SQL injections but it doesn't work. For example, when I use:
for item in self.inventory_names:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", item)
self.cursor.close()
I get the error:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 1, and there are 8 supplied.
I believe this is somehow caused by the initial creation of the database; the module I made that actually creates the DB does have 8 bindings.
cursor.execute("""CREATE TABLE Equipment
(id INTEGER PRIMARY KEY,
name TEXT,
price INTEGER,
weight REAL,
info TEXT,
ammo_cap INTEGER,
availability_west TEXT,
availability_east TEXT)""")
However, when I use the less-secure "%s" substitution for each item name, it works just fine. Like so:
for item in self.inventory_names:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = '%s'" % item)
self.cursor.close()
I can't figure out why it thinks I have 8 bindins when I'm only calling one. How can I fix it?
The Cursor.execute() method expects a sequence as second parameter. You are supplying a string which happens to be 8 characters long.
Use the following form instead:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", [item])
Python library reference: sqlite3 Cursor Objects.
I have spent half a day trying to figure out why something like this would give me an error:
cursor.execute("SELECT * from ? WHERE name = ?", (table_name, name))
only to find out that table names cannot be parametrized. Hope this will help other people save some time.
The argument of cursor.execute that represents the values you need inserted in the database should be a tuple (sequence). However consider this example and see what's happening:
>>> ('jason')
'jason'
>>> ('jason',)
('jason',)
The first example evaluates to a string instead; so the correct way of representing single valued tuple is as in the second evaluation. Anyhow, the code below to fix your error.
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item,))
Also giving the cursor.execute value arguments as strings,(which is what you are doing) results in the first evaluation in the example and results into the error you are getting.
The sqlite3 module supports two kinds of placeholders for parameters:
qmark style
Use one or more ? to mark the position of each parameter, and supply a list or tuple of parameters. E.g.:
curs.execute(
"SELECT weight FROM Equipment WHERE name = ? AND price = ?",
["lead", 24],
)
named style
Use :par placeholders for each named parameter, and supply a dict. E.g.:
curs.execute(
"SELECT weight FROM Equipment WHERE name = :name AND price = :price",
{"name": "lead", "price": 24},
)
Advantages of named style parameters is that you don't need to worry about the order of parameters, and each :par can be used multiple times in large/complex SQL queries.
have You tried this ? :
for item in self.inventory_names:
t = (item,)
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", t)
self.cursor.close()
cursor.execute() expects a sequence (list,tuple) as second parameter. (-> ddaa )
Quoting (is that what the parens mean?) the ? with parens seems to work for me. I kept trying with (literally) '?' but I kept getting
ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.
When I did:
SELECT fact FROM factoids WHERE key LIKE (?)
instead of:
SELECT fact FROM factoids WHERE key LIKE '?'
It worked.
Is this some python 2.6 thing?
each element of items has to be a tuple.
assuming names looks something like this:
names = ['Joe', 'Bob', 'Mary']
you should do the following:
for item in self.inventory_names:
self.cursor.execute("SELECT weight FROM Equipment WHERE name = ?", (item, ))
by using (item, ) you are making it a tuple instead of a string.
Try
execute("select fact from factoids where key like ?", "%%s%" % val)
You don't wrap anything around the ? at all, Python sqlite will correctly convert it into a quoted entity.
Related
I have a Oracle SQL query:
SELECT * from table1 WHERE deliveredDate = ? AND productID IN (?,?,?,...);
I would like to pass a single variable to deliveredDate and a list with length unknown to the productID using cx_Oracle and Python
From the Oracle Using Bind guide (https://cx-oracle.readthedocs.io/en/latest/user_guide/bind.html) I understand that you can bind either the single variable or list of items, but I'm not sure if we can bind both.
Please help me with this issue.
Thank you.
Of course you can, but convert the notation for bind variables from ? to :-preceeded integers such as
import pandas as pd
import cx_Oracle
import datetime
conn = cx_Oracle.connect('un/pwd#ip:port/db')
cur = conn.cursor()
sql = """
SELECT *
FROM table1
WHERE deliveredDate = :0 AND productID IN (:1,:2)
"""
cur.execute(sql,[datetime.datetime(2022, 5, 3),1,2])
res = cur.fetchall()
print(res)
The key part of your question was the 'unknown length' for the IN clause. The cx_Oracle documentation Binding Multiple Values to a SQL WHERE IN Clause shows various solutions each with some pros & cons depending on size of the list and the number of times the statement will be executed. For most cases you will not want to bind to a single placeholder in your statement IN list because of performance implications. If there is an upper bound on the size of the IN list, then put that many placeholders and bind None for all unknown values. The doc example explains it better:
cursor.execute("""
select employee_id, first_name, last_name
from employees
where last_name in (:name1, :name2, :name3, :name4, :name5)""",
name1="Smith", name2="Taylor", name3=None, name4=None, name5=None)
for row in cursor:
print(row)
(This uses keyword parameters to match the bind placeholders, but you can use a list instead).
Other solutions are shown in that doc link.
as mentioned in the title i get this error when i try to execute a prepared statement. The full error is:
RuntimeError: No matching overloads found for prepareStatement in find. at native\common\jp_method.cpp:127
As far as i can understand is, that propably that since i am trying to use a prepared statement, that the compiler can not find something to overload the ? placeholder.
Code snippet:
curs = self.dbconn.cursor()
sqlLogin = ("SELECT name,email FROM BENUTZER where name=? and email=?", ( benutzerObjekt.name,benutzerObjekt.email))
curs.execute(sqlLogin)
The error seems to happen at curs.execute(sqlLogin), which is shown to me in the traceback when debugging.
I'm trying to use the input of an html input, which is stored in benutzerObjekt.name and benutzerObjekt.email as input for the select SQL statement. So most probably something is wrong with either my SQL statement, or the execution of the statement, which is underlined when debugging. I am using db2.
Thanks in advance!
You need to pass parameters as second argument in cursor.execute. Right now your query is a nested tuple of two items with first being a string and second item being a tuple of two values.
Consider separating the arguments for function call:
curs = self.dbconn.cursor()
# SINGLE STRING VALUE
sqlLogin = "SELECT name,email FROM BENUTZER WHERE name=? AND email=?"
# TUPLE OF TWO VALUES
vals = (benutzerObjekt.name, benutzerObjekt.email)
# PASS SQL AND PARAMS SEPARATELY
curs.execute(sqlLogin, vals)
Alternatively, you can unpack your nested tuple using asterisk, *:
sqlLogin = (
"SELECT name,email FROM BENUTZER where name=? and email=?",
(benutzerObjekt.name, benutzerObjekt.email)
)
curs.execute(*sqlLogin)
I have the cursor with the query statement as follows:
cursor.execute("select rowid from components where name = ?", (name,))
I want to check for the existence of the components: name and return to a python variable.
How do I do that?
Since the names are unique, I really favor your (the OP's) method of using fetchone or Alex Martelli's method of using SELECT count(*) over my initial suggestion of using fetchall.
fetchall wraps the results (typically multiple rows of data) in a list. Since the names are unique, fetchall returns either a list with just one tuple in the list (e.g. [(rowid,),] or an empty list []. If you desire to know the rowid, then using fetchall requires you to burrow through the list and tuple to get to the rowid.
Using fetchone is better in this case since you get just one row, (rowid,) or None.
To get at the rowid (provided there is one) you just have to pick off the first element of the tuple.
If you don't care about the particular rowid and you just want to know there is a hit,
then you could use Alex Martelli's suggestion, SELECT count(*), which would return either (1,) or (0,).
Here is some example code:
First some boiler-plate code to setup a toy sqlite table:
import sqlite3
connection = sqlite3.connect(':memory:')
cursor=connection.cursor()
cursor.execute('create table components (rowid int,name varchar(50))')
cursor.execute('insert into components values(?,?)', (1,'foo',))
Using fetchall:
for name in ('bar','foo'):
cursor.execute("SELECT rowid FROM components WHERE name = ?", (name,))
data=cursor.fetchall()
if len(data)==0:
print('There is no component named %s'%name)
else:
print('Component %s found with rowids %s'%(name,','.join(map(str, next(zip(*data))))))
yields:
There is no component named bar
Component foo found with rowids 1
Using fetchone:
for name in ('bar','foo'):
cursor.execute("SELECT rowid FROM components WHERE name = ?", (name,))
data=cursor.fetchone()
if data is None:
print('There is no component named %s'%name)
else:
print('Component %s found with rowid %s'%(name,data[0]))
yields:
There is no component named bar
Component foo found with rowid 1
Using SELECT count(*):
for name in ('bar','foo'):
cursor.execute("SELECT count(*) FROM components WHERE name = ?", (name,))
data=cursor.fetchone()[0]
if data==0:
print('There is no component named %s'%name)
else:
print('Component %s found in %s row(s)'%(name,data))
yields:
There is no component named bar
Component foo found in 1 row(s)
I have found the answer.
exist = cursor.fetchone()
if exist is None:
... # does not exist
else:
... # exists
As both existing answers (your own and #unutbu's) point out, the trick is that you do need to do some sort of fetching, after executing the SELECT, to check whether there have been any results to the select or not (whether you do it with a single fetch and check for none, or a fetch-all and check for an empty list, is a marginal difference -- given that you mention a UNIQUE constraint they're basically equivalent approaches).
For a very direct answer, you could select count(*) from components where name = ?, rather than selecting rowid, if all you care is whether the given value for name is present or not (as opposed to, caring about what row id it's on, if at all;-). Executing this select, and fetching the result, gives you 0 if the value is absent, 1 if it's present (no other result is possible given what you mentioned in a comment about the UNIQUE constraint on column name;-).
Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), we can slightly modify previous answers by capturing the result of cursor.fetchone() within the condition check and re-use it to extract the result content:
# cursor.execute("SELECT rowid FROM components WHERE name = ?", (name,))
if item := cursor.fetchone():
print(f'Component {name} found with rowid {item[0]}')
else:
print(f'There is no component named {name}')
To make it even shorter...:
row = cursor.fetchone()
if row:
print "row is present"
else:
print "row is not present"
The reason mine was showing the "Lock" message was actually due to me having opened an SQLite3 IDE on my Windows and that was the reason it was locked. I assume I was playing around with the DB within the IDE and hadn't saved the changes and therefor a lock was placed.
This is what worked for me
exist = conn.execute("select rowid from rowid where name = ?", (name,)).fetchone()
if exist is None:
print("Doesn't exist")
else:
print("Yep exists")
I am trying to search my SQLite3 database using a pythonic variable as a search term. The term I'm searching for is a part of the contents of the cell in the database (e.g. Smith in a cell: [Harrison GB, Smith JH]) and is often in the middle of the string in a cell.
I have tried to code it as shown below:
def read_from_db():
c.execute("SELECT authors, year, title, abstract FROM usertable WHERE authors LIKE (?)",(var1,))
data = c.fetchall()
print(data)
for row in data:
searchlist.append(row)
var1="Smith"
read_from_db()
This should show the results row after row. However, I get 0 results when var1 = "Smith". When I change its value to "Harrison GB, Smith JH", I get all the results.
When I try to solve it by changing the SQLite3 execute query I yield an error.
ERROR
c.execute("SELECT authors, year, title, abstract FROM usertable WHERE authors LIKE '%?%'",(var1,))
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.
I get syntax errors if I change the endings with: $?$, (%?%) etc. I tried this with:
...authors="%?%"
But this doesn't work either. There is a few similar questions on SO, but they don't exactly solve my issue...
I am running Python 3.4 and SQLite3 on Windows 10.
Consider concatenating the % wildcards to the binded value, var1:
c.execute("SELECT authors, year, title, abstract" +
" FROM usertable WHERE authors LIKE (?)", ('%'+var1+'%',))
The reason you need to do so is the ? placeholder substitutes a string literal in parameterized queries and for LIKE expressions, wildcards with values together are string literals as denoted by their enclosed single quotes:
SELECT authors, year, title, abstract FROM usertable WHERE authors LIKE '%Smith%'
Your initial attempt failed because you wrap ? with single quotes and the cursor cannot bind the param to prepared statement properly and so the symbol is taken literally as question mark.
I'm trying execute a simple query, but getting this error no matter how I pass the parameters.
Here is the query (I'm using Trac db object to connect to a DB):
cursor.execute("""SELECT name FROM "%s".customer WHERE firm_id='%s'""" % (schema, each['id']))
schema and each['id'] both are simple strings
print("""SELECT name FROM "%s".customer WHERE firm_id='%s'""" % (schema, each['id']))
Result:
SELECT name FROM "Planing".customer WHERE firm_id='135'
There is on error is a remove quote after firm_id=, but that way parameter is treated a an integer and ::text leads to the very same error.
In my case I didn't realize that you had to pass a tuple to cursor.execute. I had this:
cursor.execute(query, (id))
But I needed to pass a tuple instead
cursor.execute(query, (id,))
I got this same error and couldn't for the life of me work out how to fix, in the end it was my mistake because I didn't have enough parameters matching the number of elements in the tuple:
con.execute("INSERT INTO table VALUES (%s,%s,%s,%s,%s)",(1,2,3,4,5,6))
Note that I have 5 elements in the values to be inserted into the table, but 6 in the tuple.
It is recommended to not use string interpolation for passing variables in database queries, but using string interpolation to set the table name is fine as long as it's not an external input or you restrict the allowed value. Try:
cursor.execute("""
SELECT name FROM %s.customer WHERE firm_id=%%s
""" % schema, (each['id'],))
Rules for DB API usage provides guidance for programming against the database.
Use AsIs
from psycopg2.extensions import AsIs
cursor.execute("""
select name
from %s.customer
where firm_id = %s
""",
(AsIs(schema), each['id'])
)
You could try this:
cursor.execute("INSERT INTO table_name (key) VALUES(%s)",(value1,))
You will get an error if you are missing a (,) after value1.
The correct way to pass variables in a SQL command is using the second argument of the execute() method. And i think you should remove single quotes from second parameter, read about it here - http://initd.org/psycopg/docs/usage.html#the-problem-with-the-query-parameters.
Note that you cant pass table name as parameter to execute and it considered as bad practice but there is some workarounds:
Passing table name as a parameter in psycopg2
psycopg2 cursor.execute() with SQL query parameter causes syntax error
To pass table name try this:
cursor.execute("""SELECT name FROM "%s".customer WHERE firm_id=%s""" % (schema, '%s'), (each['id'],))
Every time I have this kind of error, I am passing the wrong amount of values. Try check it