Passing multiple arguments in SQL - Python - python

I am trying to pass two arguments into a SQL statement as below:
cursor.execute(f"""select * from table
where product_name = '{prod_name}' and date = '{sale_date}'"""")
I am trying to have this run through a loop for several combination so I am trying to see how I can have this altered accordingly.
prod_name = ['prod_a','prod_b']
sale_date = ['2020-01-01','2020-02-01']
I know how to pass one argument through a loop but I am not sure how to pass more than one argument together at the same.

It's a security danger to add variables directly to your SQL query. cursor.execute provides sanitizing as long as you pass the arguments as the second argument of the function call.
Example:
cursor.execute("select * form table where product_name = '%s' and date = '%s'", (prod_name, sale_date))
To loop through multiple lists at once you can do the following (assuming the lists have the same amount of values):
for i in range(len(prod_name)):
cursor.execute("select * form table where product_name = '%s' and date = '%s'", (prod_name[i], sale_date[i]))
By looping through a range I get the numbers of 0 - len(prod_name) and as I loop with the index of i I can use that to retrieve the first item in both lists.
Sam Mason had a good comment about using the zip function which combines iterators and can be used like so:
for args in zip(prod_name, sale_date):
cursor.execute("select * form table where product_name = '%s' and date = '%s'", args)

try this :
results = ()
dc = ['103,4770634', '42,427752', '64,10122045', '42,13603629', '42,25516425', '103,2748102', '42,1966402', '42,30262834', '42,6667711', '18,13737683', '42,28921168', '42,26076925', '103,3733654', '42,23313527', '64,3307344', '103,3973533', '42,6360982', '48,11846077', '103,3775309', '64,10122050', '42,1965119', '103,4265810', '103,3971645', '103,4962583', '103,689615', '42,22834366', '103,761655', '95,1184', '64,9594482', '42,22855603', '48,8654764', '103,4226756', '42,23366982', '103,3897036', '42,11339650', '101,6369', '42,25830920', '103,5009291', '42,29238961', '59,6299475', '42,22931663', '42,25839056', '43,11864458', '43,41346192', '103,4261645', '42,3747082', '103,4795050', '42,9417503', '103,4245623', '42,61431911']
try:
sql = "SELECT * FROM tbl1 WHERE id1 in (%s) AND id2 in (%s)"
in_ids = ', '.join(map(lambda x: '%s', dc))
in_ids = in_ids % tuple(dc)
sql = sql % (in_ids, in_ids)
cursor.execute(sql)
res = cursor.fetchall()
results = results + res
except Exception, e:
print e

Related

List index out of range for Python

I have a question regarding the following exercise:
def addstock():
time = datetime.now().strftime("%B %d, %Y")
hour = datetime.now().strftime("%I:%M%p")
query = 'SELECT TotalStock FROM Stocks WHERE name = ? ORDER BY MovementID DESC LIMIT 1'
parameters = (name.get(),)
lastrecord = run_query(query, parameters)
print(float(lastrecord.fetchall()[0][0]))
print(float(quantity.get()))
totalstock = (float(lastrecord.fetchall()[0][0])) + (float(quantity.get()))
query = 'SELECT precio FROM product WHERE name = ?'
precio = run_query(query, parameters)
pricequant = precio.fetchall()[0]
pricequantity = pricequant * quantities
query = 'SELECT precio FROM product WHERE name = ?'
parameters = (name.get(),)
precio = run_query(query, parameters)
priceforall = pricequant * totalstock
In this function, I print lastrecord.fetchall()[0][0] and quantity.get to make sure they are float. So the program prints in that case: 5.0 for lastrecord.fetchall and quantity.get
Up to now, no problem, but when I try to us them up, it gives me an error of List Index Out Of Range, so program do not find the value of lastrecord.fetchall()[0][0] which 2 lines before I was able to print successfully. Can someone explain why?
According to documentation:
The method fetches all (or all remaining) rows of a query result set and returns a list of tuples. If no more rows are available, it returns an empty list.
When you first time used lastrecord.fetchall()[0][0] all the records of lastrecord curser are fetched, so on the second call on totalstock = (float(lastrecord.fetchall()[0][0])) + (float(quantity.get())) there is no more rows left for the curser. If you want to reuse the fetched data, store it, then use it anytime you want, like this:
all_records = lastrecord.fetchall()
// ...
print(float(all_records[0][0]))
// ...
totalstock = (float(all_records[0][0])) + (float(quantity.get()))

Query a mysql table for a dynamic column name and its value in python?

I want to search a mysql table for rows where the specified column has a particular value. For example, given the input string memory=2048 it will search for the rows that have "2048" as the value of memory column and it will print them.
This is code that I have tried but it print outs nothing.
input = input()
tag = input.split("=")
desc = tag[1]
tag = tag[0]
mycursor = mydb.cursor()
sql = "(SELECT * FROM comp WHERE %s LIKE %s)"
val = (tag, desc)
mycursor.execute(sql, val)
res = mycursor.fetchall()
for x in res:
print(x)
Secondly I tried this code to see where is the problem :
input = input()
tag = input.split("=")
desc = tag[1]
tag = tag[0]
mycursor = mydb.cursor()
sql = "(SELECT * FROM comp WHERE memory LIKE '2048')"
mycursor.execute(sql)
res = mycursor.fetchall()
for x in res:
print(x)
It gives the desired output. So my problem is when I am trying to get the column name with %s it comes as 'memory' and It couldn't finds it, since the name of the column is memory. Is there a way to get rid of the '' chars ?
confirmation of inputs
Looking at the mysql.connector's execute() documentation it appears to use %s as placeholders for bind parameters.
So your execute("SELECT * FROM comp WHERE %s LIKE %s", ("memory", "2048")) call ends up running like the following SQL:
SELECT * FROM comp WHERE 'memory' LIKE '2048'
obviously returning 0 rows.
You need to put the literal column name into the query text before invoking execute():
sql = "SELECT * FROM comp WHERE %s LIKE %s" % (tag, "%s")
# => "SELECT * FROM comp WHERE memory LIKE %s"
mycursor.execute(sql, (desc, ))

How do I use variables as attribute names when using python mysql connector

I am trying to use variables in a python function to try and retrieve attributes with mysql connector
It seems to work only when I specify the name of the attribute in the query itself
def insert(ids, added_attribute):
insert = ''
if len(ids) > 0:
#insert scpecified attributes wanted
insert += ' AND (%s = %s' %(added_attribute, ids[0])
#for loop for more than one specified specific attribute
for id_index in range(1, len(ids)):
insert += ' OR %s = %s' %(added_attribute, ids[id_index])
insert += ')'#close parenthesis on query insert
return insert
def get(name, attributes = 0, ids = []):
cursor = conn.cursor()
#insert specific ids
insert = insert(ids, "id")
query = 'SELECT %s FROM (TABLE) WHERE (name = %s%s)'
cursor.execute(query, (attributes, name, insert))
data = cursor.fetchall()
cursor.close()
return data
I keep getting null as a return value
Try this...
query = 'SELECT {} FROM (TABLE) WHERE (name = {}{})'
cursor.execute(query.format(attributes, name, insert))
{} is replacing %s here and to call the variables you just need to add .format() with the vars you want inserted in order.

How to pass element from array to query

I would like to know, how I want to write some code, which gives me the index of element found in database.
I have function like this:
def get_teachers_names(name, lastname):
try:
params = config()
conn = psycopg2.connect(**params)
cur = conn.cursor()
select_query = "SELECT id FROM lecturers WHERE name = %s AND lastname = %s"
record_to_find = (name, lastname)
cur.execute(select_query, record_to_find)
records = list(cur)
conn.commit()
cur.close()
return records
except (Exception, psycopg2.DatabaseError) as error:
print(error)
When I do something like:
index = database.get_teachers_names('Name1', 'Surname1')
I get index I want. But when I have a lists:
names = ('Name1', 'Name2')
surnames = ('Surname1', 'Surname2')
And I try to do the same with:
index = database.get_teachers_names(names[0], surnames[0]
I get [] as result. I also tried:
index = database.get_teachers_names(''.join(names[0], ''.join(surnames[0]))
But it also didn't work. Any suggestions?
It works when you pass a simple strings as they will populate the query string correctly:
index = database.get_teachers_names('Name1', 'Surname1')
However when you pass a list it won't be parsed correctly as a string in:
"SELECT id FROM lecturers WHERE name = %s AND lastname = %s"
I think the best approach for you is to loop over the list and execute this for each entry:
cur.execute(select_query, record_to_find)
You can then append the results to a the records list.

Python - MySQL queries with parametres and comas

I'm learning programming with python and trying to implement the safest possible MySQL queries starting with the simple SELECT ones. The problem is whenever I use coma in a query I got the following error:
cursor.execute(query)
File "C:\Users\username\AppData\Local\Programs\Python\Python37-32\lib\site-packages\mysql\connector\cursor.py", line 536, in execute
stmt = operation.encode(self._connection.python_charset)
AttributeError: 'tuple' object has no attribute 'encode'
I am aware of the fact that coma itself isn't a source of a problem but I tried many different MySQL syntax and everytime I use a come I got this "AttributeError: 'tuple' object has no attribute 'encode'" error.
I also tried to change MySQL database encoding - nothing changes. The code is below.
import mysql.connector
conn = mysql.connector.connect(
charset='utf8',
# init_command='SET NAMES UTF8',
host="10.0.0.234",
user="x",
passwd="x>",
database="x",
)
print(conn.is_connected())
param = "test"
cursor = conn.cursor()
# =========== query below does work ========
# query = ("SELECT * from list WHERE username LIKE '%test%'")
# ============ query below does work =======
# query = ("SELECT * from list HAVING username = '%s'" % param)
# ============ query below doesn't work =====
# query = ("SELECT * from list HAVING username = %s", (param,))
# ============= query below doesn't work =====
query = "SELECT * from list WHERE username = :name", {'name': param}
cursor.execute(query)
result = cursor.fetchall()
for x in result:
print(x)
conn.close()
Any ideas what am I doing wrong?
The answer is a little bit tricky, but it is in essence because of what the actual value of the 'query' variable is...
For example:
# 1.
query = ("SELECT * from list WHERE username LIKE '%test%'")
# when you do this, query is a string variable,
# NB: the parentheses are not necessary here
# so when you call
cursor.execute(query)
# the value passed into the execute call is the string "SELECT * from list WHERE username LIKE '%test%'"
# 2.
query = ("SELECT * from list HAVING username = '%s'" % param)
# when you do this, query is the result of a string formatting operation
# This is a Python 2 form of string formatting
# The discussion here probably makes it more clear:
# https://stackoverflow.com/questions/13945749/string-formatting-in-python-3
# it is almost the same as doing this:
query = "SELECT * from list HAVING username = 'test'"
# so when you call
cursor.execute(query)
# the value passed into the execute call is the string "SELECT * from list HAVING username = 'test'"
# 3.
query = ("SELECT * from list HAVING username = %s", (param,))
# This operation is assigning a 2-value tuple into the query variable
# The first value in the tuple is the string "SELECT * from list HAVING username = %s"
# The second value in the tuple is a 1-value, with 'test' as its first value
# 4.
query = "SELECT * from list WHERE username = :name", {'name': param}
# This is similar to #3, but the values in the tuple are instead
# query[0] == "SELECT * from list WHERE username = :name"
# query[1] is a dictionary: {'name': param}
Both 3 and 4 above are not calling the MySQL execute with the parameters you are expecting (see API here). You probably need to do one of:
unpack the query tuple into separate variables, and call the function with them
operation, params = query # unpack the first elem into operation, and second into params
cursor.execute(operation, params)
just index into the query tuple
cursor.execute(query[0], query[1])
# NB: you could also use the 'named parameters' feature in Python
cursor.execute(query[0], params=query[1])
Use the 'unpacking arguments list' (SPLAT operator)
cursor.execute(*query)

Categories

Resources