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)