Python error when searching sqlite3 database - python

#!/usr/bin/python
import sqlite3
conn = sqlite3.connect("/home/michael/Dropbox/lagniappe/database.db")
cursor = conn.cursor()
query = raw_input('Search for a title:')
cursor.execute("SELECT * FROM nerd WHERE title LIKE '%?%';", query)
print cursor.fetchall()
Retuns the error:
michael#piplup:~$ python sqlite.py
Search for a title:test
Traceback (most recent call last):
File "sqlite.py", line 10, in <module>
cursor.execute("SELECT * FROM nerd WHERE title LIKE '%?%';", query)
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 4 supplied.
All I want it to do is to print out the data it receives from the database to the console. Eventually I would like to manipulate this data, but I just need the query to work right.

There are two problems here. First, the parameter is supposed to be a sequence - Python is interpreting it as a list of four characters, rather than a four-character string.
Secondly, the placeholder has to be the entire element, and not in quotes. You'll need to add the percent characters yourself:
query = raw_input('Search for a title:')
query = '%' + query + '%'
cursor.execute("SELECT * FROM nerd WHERE title LIKE ?", (query,))

First, the second parameter of the execute method is supposed to be a sequence, and you are passing a string (which is interpreted as a sequence of characters), that's why it says ... and there are 4 supplied.
Second, the quotes around the argument of your LIKE comparison prevent the execute method to interpret the ? as a placeholder; instead it's being interpreted as the literal ?.
So, for your query to work correctly, you have to do two things:
Add the % to your the query argument, insted of embedd them into the SQL query.
Pass the query argument inside a sequence (a one-element tuple or list).
Here's how your script would look like:
#!/usr/bin/python
import sqlite3
conn = sqlite3.connect("/home/michael/Dropbox/lagniappe/database.db")
cursor = conn.cursor()
query = '%%%s%%' % raw_input('Search for a title:') # puts the input between %
cursor.execute("SELECT * FROM nerd WHERE title LIKE ?;", (query,)) # passes the query as a tuple
print cursor.fetchall()

You need to pass a tuple to cursor.execute. Try (query,) instead of query.
cursor.execute("SELECT * FROM nerd WHERE title LIKE '%?%';", (query,))

Related

Receiving Error not all arguments converted during string formatting

I am new to working on Python. I m not able to understand how can I send the correct input t0 the query.
list_of_names = []
for country in country_name_list.keys():
list_of_names.append(getValueMethod(country))
sql_query = f"""SELECT * FROM table1
where name in (%s);"""
db_results = engine.execute(sql_query, list_of_names).fetchone()
Give the error " not all arguments converted during string formatting"
As implied by John Gordon's comment, the number of placeholders in the SQL statement should match the number of elements in the list. However SQLAlchemy 2.0+ no longer accepts raw SQL statements. A future-proof version of the code would be:
import sqlalchemy as sa
...
# SQL statements should be wrapped with text(), and should used
# the "named" parameter style.
sql_query = sa.text("""SELECT * FROM table1 where name in :names)"""
# Values should be dictionaries of lists of dictionaries,
values = {'names': list_of_names}
# Execute statements using a context manager.
with engine.connect() as conn:
db_results = conn.execute(sql_query, values).fetchone()
If I know right, there are a simpler solution. If you write curly bracets {}, not bracets (), and you place inside the bracets a variable, which contains the %s value, should work. I don't know, how sql works, but you should use one " each side, not three.
Sorry, I'm not english. From this, maybe I wasn't help with the question, because I don't understand correctly.

Passing parameters to LIKE SQL query

I want to pass dynamic parameter to the LIKE query using Fast API (Python) coming from the query parameter. I have tried a lot of ways but I don't know what I am doing wrong.
The query I need to use is :
SELECT Time, table_id, Text FROM tablename WHERE Text LIKE '%text%'
The python code for getting query parameter is :
def get_result(text : str):
con = connection.connect()
statement = 'SELECT Time, table_id, Text FROM tablename WHERE Text LIKE '%text%''
How will I pass the dynamic text parameter in this query because this gives the error saying "TypeError: not all arguments converted during string formatting"?
You cannot nest single quotes. Also, it's clearer to use a f-string for string formatting here. Try:
statement = f"SELECT Time, table_id, Text FROM tablename WHERE Text LIKE '%{text}%'"
NEVER substitute values directly in to a SQL string like that. EVER. Use parameterised queries / bind variables.
For example, depending on the driver/library you're using, you may be able to use...
con = connection.connect()
cur = con.cursor()
cur.execute("SELECT Time, table_id, Text FROM tablename WHERE Text LIKE %s", ('%' + text + '%',))

MySQLdb adding character b infront of strings that have been escaped - Python

I am trying to write a simple Python script to bulk add movie titles into a local database, using the MySQLdb (mysqlclient) package. I am reading the titles from a TSV file. But when go to sanitize the inputs using MySQLdb::escape_string(), I get the character b before my string. I believe this means that SQL is interpreting it as a bit value, but when I go to execute my query I get the following error:
You have an error in your SQL syntax; check the manual that
corresponds to your MariaDB server version for the right syntax to use
near 'b'Bowery to Bagdad',1955)' at line 1"
The select statement in question:
INSERT INTO movies (imdb_id, title, release_year) VALUES ('tt0044388',b'Bowery to Bagdad',1955)
def TSV_to_SQL(file_to_open):
from MySQLdb import _mysql
db=_mysql.connect(host='localhost', user='root', passwd='', db='tutorialdb', charset='utf8')
q = """SELECT * FROM user_id"""
# MySQLdb.escape_string()
# db.query(q)
# results = db.use_result()
# print(results.fetch_row(maxrows=0, how=1))
print("starting?")
with open(file_to_open, encoding="utf8") as file:
tsv = csv.reader(file, delimiter="\t")
count = 0
for line in tsv:
if count == 10:
break
# print(MySQLdb.escape_string(line[1]))
statement = "INSERT INTO movies (imdb_id, title, release_year) VALUES ('{imdb_id}',{title},{year})\n".format(
imdb_id=line[0], title=MySQLdb.escape_string(line[1]), year=line[2])
# db.query(statement)
print(statement)
count = count + 1
I know a simple solution would be to just remove the character b from the start of the string, but I was wondering if there was a more proper way, or if I missed something in documentation.
The 'b' infront of the string represents that the string is binary encoded rather than a literal string.
If you use .encode() you will be able to get what you want.
How to convert 'binary string' to normal string in Python3?
It's more common to let the connector perform the escaping automatically, by inserting placeholders in the SQL statement and passing a sequence (conventionally a tuple) of values as the second argument to cursor.execute.
conn = MySQLdb.connect(host='localhost', user='root', passwd='', db='tutorialdb', charset='utf8')
cursor = conn.cursor()
statement = """INSERT INTO movies (imdb_id, title, release_year) VALUES (%s, %s, %s)"""
cursor.execute(statement, (line[0], line[1], line[2]))
conn.commit()
The resulting code is more portable - apart from the connection it will work with all DB-API connectors*. Dropping down to low-level functions like _mysql.connect and escape_string is unusual in Python code (though you are perfectly free to code like this if you want, of course).
* Some connection packages may use a different placeholder instead of %s, but %s seems to be the favoured placeholder for MySQL connector packages.

Fetch one row from MySQL table

I'm trying to fetch one row of a MySQL table based on a user input. My code is:
"""Get entry information"""
reinforcement_name = reinforcement_input.get()
"""Fetch reinforcement data"""
mycursor = mydb.cursor()
sql_select_query = "select '*' from reinforcement where name = '%s'"
mycursor.execute(sql_select_query, reinforcement_name)
reinforcement_data = mycursor.fetchone()
print(reinforcement_data)
I'm expecting to get a list of column entries for that specific user input. However, I'm getting None printed out rather than a list.
How can I have my reinforcement_data presented as the list I'm expecting?
The fetchone call is OK. The problem is with your query - when you use a parameterized query, you should not use quotes around the bind variables - these aren't simple string replacements, but bind variables the database driver handles. Here, you're querying for a row with the literal name of %s, which probably doesn't exist. The parameters need to pass to execute as an iterable.
On a related note, you should also remove the quotes around the * in the select list, otherwise, you'll get the asterisk literal, not all the columns.
sql_select_query = "select * from reinforcement where name = %s"
# No quotes --------------^-^-------------------------------^--^
mycursor.execute(sql_select_query, (reinforcement_name,))
# Params passed as a tuple --------^

Python mysql connector LIKE against unicode value

So here is my problem: I am trying to select a specific value from a table
comparing it with a unicode string. The value is also unicode. I am using
mysql.connector. The server settings are all utf8 oriented. When I run
following query - I get an empty list. When I run it without 'WHERE Title like '%s'' part, I get a full set of values, and they properly displayed in the
output. The same query works in the command line on the server. The value is
there for sure. What is it that I am missing?
conn = sql.connect(host='xxxxxxx', user='xxx', password='xxx', database='db', charset="utf8")
cur = conn.cursor()
townQuery = (u"""SELECT * FROM Towns WHERE Title like '%s' """)
tqd = (u"%" +u"Серов"+u"%")
cur.execute(townQuery, tqd)
for i in cur:
print i
When you use the 2-argument form of cur.execute (thus passing the arguments, tqd, to the parametrized sql, townQuery), the DB adaptor will quote the arguments for you. Therefore, remove the single quotes from around the %s in townQuery:
townQuery = u"""SELECT * FROM Towns WHERE Title like %s"""
tqd = [u"%Серов%"]
cur.execute(townQuery, tqd)
Also note that the second argument, tqd, must be a sequence such as a list or tuple. The square brackets around u"%Серов%" makes [u"%Серов%"] a list. Parentheses around u"%Серов%" do NOT make (u"%Серов%") a tuple because Python evaluates the quantity in parentheses to a unicode. To make it a tuple, add a comma before the closing parenthesis: (u"%Серов%",).

Categories