placeholders for table names in python mysql - mysql

I am using python sql to edit a very simple table named students (whose columns are name and age), as shown below:
('Rachel', 22)
('Linckle', 33)
('Bob', 45)
('Amanda', 25)
('Jacob', 85)
('Avi', 65)
('Michelle', 45)
I am defining python functions to execute SQL code.
In my first function I want to update the age values in students table where the name matches something (e.g. Bob). If I define the following function:
def update_age(age, name):
c.execute("""UPDATE students SET age = %s
WHERE name = %s""", (age, name))
And then:
update_age(99, 'Bob')
I will get:
('Rachel', 22)
('Linckle', 33)
('Bob', 99)
('Amanda', 25)
('Jacob', 85)
('Avi', 65)
('Michelle', 45)
On a second function I would like to specify also the name of the table, with the following code:
def update_age_table(table, age, name):
c.execute("""UPDATE %s SET age = %s
WHERE name = %s""",
(table, age, name)) # note that here I am only replacing students by the placeholder %s
Then if I do:
update_age_table(table='students', age=95, name='Jacob')
I will get the following error message (it is long, I am only displaying the last sentence:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''students' SET age = 95
WHERE name = 'Jacob'' at line 1
I guess that the error comes from the fact that I am assigning two of the placeholders to variables, namely age and name, which is not the case of the table name, where there is no variable assignment.
Does anyone know how I can use placeholders in SQL commands without assigning them to variables?

ThatÅ› because you cannot pass the table name as a parameter in the execute sentence. You should do it this way:
def update_age_table(table, age, name):
c.execute("UPDATE "+table+" SET age = %s
WHERE name = %s",
(table, age, name)) #
The prepared statement doesn't work for table names
EDIT
You have to remove the table parameter like this:
def update_age_table(table, age, name):
c.execute("UPDATE "+table+" SET age = %s WHERE name = %s",(age, name)) #
Sorry was a mistake

dt= datetime.datetime.now()
new_date=str(dt)
idname=input("Please enter Your Id. ")
bname= input("Please Enter name of book which you want to Issue: ")
idn=(idname,)
sql="insert into id%s (issuedbook,date)"%idn +"values (%s,%s)"
val=(bname,new_date)
cursor.execute(sql,val)
cnx.commit()
insert_data()```

Without having tested it, this should be a better coding style of the accepted answer. As the whole Q/A shows, the variables are passed only at cursor.execution() time to make it more secure, but the table statement of the execute() string is evaluated before the args are evaluated, that is why tables have to be plain text evaluated before execute() but the variables do not. See another example with similar challenge at Python - pass a list as params to SQL, plus more variables where the table is not passed either.
Therefore, just as an add-on for the rightly accepted query:
def update_age_table(UPDATE_QUERY, args):
c.execute(UPDATE_QUERY, args)
c.commit()
# example for string testing:
table, age, name = "table_x", 2, "name_y"
UPDATE_QUERY = f"""
UPDATE {table}
SET age = %s
WHERE name = %s
"""
# # UPDATE_QUERY Out:
# '\n UPDATE table_x\n SET age = %s\n WHERE name = %s\n'
args = [age, name]
update_age_table(UPDATE_QUERY, args)

Related

mySQL / Python Problems

I am a new A-Level student, doing AS computer science.
I really don't know how to fix this problem but I need help with the following code.
I am trying to incorporate mySQL into Python and query data successfully. I also am trying to update a certain table via python. I am running into problems however that seem to throw errors that aren't actually happening as far as I can see. Am I blind? I hope that you geniuses can help me work it out.
The problem I have is that the SQL query I try to execute does not work and throws the following error (if the name I enter is 'Harvey', for example):
raise errors.get_exception(packet)
mysql.connector.errors.ProgrammingError: 1054 (42S22): Unknown column 'Harvey' in 'field list'
#Here is the actual code. It's trying to update a table record for name, DOB, and city by sorting via a unique 'key_field' identifier.
if int(key) < 1 or int(key) > len(ages):
print("The Key Field Number you entered is out of range of the data we have. Try again.")
continue
else:
n = input("""
Enter the name for the new record: """)
if len(n) > 50:
print("The name you entered is too long, try again.")
continue
c = input("""
Enter the name of the city for the new record: """)
if len(c) > 30:
print("The city you entered is too long. Try again.")
continue
dob_year = input("""
Entering the DOB (Date of Birth) for the new record...
Enter the year (YYYY): """)
if len(dob_year) != 4:
print("The year you enter must be 4 numbers long. Try again.")
continue
dob_month = input("Enter the month (MM): ")
if len(dob_month) > 2 or len(dob_month) < 1:
print("The month you enter must be 2 numbers long. Try again.")
continue
if len(dob_month) == 1:
dob_month = "0" + dob_month
dob_day = input("Enter the day (DD): ")
if len(dob_day) > 2 or len(dob_day) < 1:
print("The day you enter must be 2 numbers long. Try again.")
continue
if len(dob_day) == 1:
dob_day = "0" + dob_day
try:
int(dob_day)
int(dob_month)
int(dob_year)
except:
print("Enter integer values for the DOB (Date of Birth) section. Try again.")
continue
else:
d = "%s-%s-%s" % (dob_year, dob_month, dob_day)
ndc = []
ndc.append(n)
ndc.append(d)
ndc.append(c)
ndc = tuple(ndc)
key = int(key)
sql = "UPDATE ppl SET name = %s, dob = %s, city = %s WHERE key_field = %s" % (ndc[0], ndc[1], ndc[2], key)
mycursor.execute(sql)
mydb.commit()
You are building a string with out the proper single quotes that mysql needs t identify strings, so it takes them as colum nnames, but you should use the prepared statements that you already have
sql = "UPDATE ppl SET name = %s, dob = %s, city = %s WHERE key_field = %s"
mycursor.execute(sql,(ndc[0], ndc[1], ndc[2], key))
mydb.commit()

Python errors occurring trying to insert data into a MySQL database table

I need to create an sql login/ sign up system for my program, however I keep hitting this error no matter what I do to change it. I need to have a randomly generated UTID, the users first and surname, along with a password that is verified, then the UserID is generated by taking the first three letters of the first name and the whole surname. I cant figure out how to overcome this.
I have tried to give the values inside the sql statement when inserting some literal datatypes, like writing "
c.execute('insert INTO tbl_Teachers (str(UTID), str(FName), str(SName), str(userPass), str(userID))VALUES(?,?,?,?,?);', var_insert) " but nothing seems to work.
def signup():
name = []
surname = []
print("Please enter the following details.")
user_type = str(input("Are you a teacher or a student: "))
if user_type == ("teacher") or ("Teacher"):
var_FName = str(input("First Name: "))
var_LName = str(input("Last Name: "))
var_password1 = str(input("Choose a password: "))
var_password2 = str(input("Please confirm password: "))
UTID = str(random.randint(0,100000))
print ("Your UserID is "+UTID+"")
name.append(var_FName)
surname.append(var_LName)
userID = []
for x in range (0, 3):
userID.append(var_FName[x])
for x in range (0,len(var_LName)):
userID.append(var_LName[x])
print (userID)
if var_password1 != var_password2:
print("Please try again.")
else:
var_insert = []
var_insert.append(UTID)
var_insert.append(var_FName)
var_insert.append(var_LName)
var_insert.append(str(var_password1))
var_insert.append(userID)
conn = sqlite3.connect('Program.db')
c = conn.cursor()
c.execute('insert INTO tbl_Teachers (UTID, FName, SName, userPass, userID)VALUES(?,?,?,?,?);', var_insert)
conn.commit()
InterfaceError: Error binding parameter 4 - probably unsupported type.
userID is supposed to be a string, but you're creating a list. Use string concatenation, not the append method.
userID = var_FName[0:3] + var_LName

Python string formatting on MySQL query

I'm trying to execute a query using two parameters, one is a list and the other is a number.
Here is my code:
cursor.execute("SELECT cod_art, price_EU, price_third_country
FROM lt_gamma_articles
WHERE cod_art in (%s) AND cod_store = %d
ORDER BY cod_art, timestamp"
% format_strings, tuple(cod_art_int), int(shop) )
I get this error:
TypeError: not enough arguments for format string
I think the error is in the string formatting, but I don't know how to format it correctly and I've been stuck for a while.
From the looks of your code, I'm gussing your basing it off of imploding a list for use in a python MySQLDB IN clause. Assuming that's the case, and
format_strings is built similar to:
format_strings = ','.join(['%s'] * len(cod_art_int))
I would use .format to build the query string, and build up a list for the positional query parameters:
query_params = list(cod_art_int)
query_params.append(int(shop))
query_sql = """
SELECT cod_art, price_EU, price_third_country
FROM lt_gamma_articles
WHERE cod_art IN ({cod_art_list}) AND cod_store = %s
ORDER BY cod_art, timestamp
""".format(cod_art_list=format_strings)
cursor.execute(query_sql, query_params)
Explanation:
Say cod_art_int is this list of integer values:
cod_art_int = [10, 20, 30]
In order to use those values in the cod_art IN (...) part of the query, you need to add a %s for each one. That is done by:
format_strings = ','.join(['%s'] * len(cod_art_int))
Which can be broken down to:
step_one = ['%s'] * len(cod_art_int)
# ['%s', '%s', '%s']
format_strings = ','.join(step_one)
# '%s,%s,%s'
When you build the final query string, you replace {cod_art_list} with format_strings:
query_sql = """
SELECT cod_art, price_EU, price_third_country
FROM lt_gamma_articles
WHERE cod_art IN ({cod_art_list}) AND cod_store = %s
ORDER BY cod_art, timestamp
""".format(cod_art_list=format_strings)
And you get the query string:
SELECT cod_art, price_EU, price_third_country
FROM lt_gamma_articles
WHERE cod_art IN (%s,%s,%s) AND cod_store = %s
ORDER BY cod_art, timestamp
Then your query parameters will be safely substituted within the query to replace the %ss. You build up the parameter list to correspond to the %ss. Since cod_art IN (%s,%s,%s) is first, you add that to the list first, followed by the value for cod_store (int(shop) which I'm going to say is 456):
query_params = list(cod_art_int)
# [10, 20, 30]
query_params.append(int(shop))
# [10, 20, 30, 456]
In the end you execute the query with its parameters:
cursor.execute(query_sql, query_params)

Mysql query with column name in spaces

I have a table with columns machine id like (311a__) and (311bb__) and some of them like (08576). How can I retrieve them in SQL - how to insert into row where machine ID is like ( 311a__)? My question how to insert and select a column which has spaces in it.. How to retrieve data where machine_name ="%s__" is it correct
sql_local = """SELECT id FROM customer_1.pay_machines WHERE machine_name="%s" """ % machine
retVal = cursor.execute(sql_local)
if (retVal == 0):
sql_local = """INSERT INTO customer_1.pay_machines (machine_name, carpark_id) VALUES ("%s", 0)""" % machine
Surround odd (or reserved word) column names with backticks:
SELECT *
FROM pd
WHERE `machine id` = '(%s__)';
edit: removed invalid insert query as the first query is sufficient as an example

How to do this lookup more elegantly in Python and MySQL?

I have a bunch of files in a directory named with nameid_cityid.txt, nameid and cityid being the ids of name (integer(10)) and city (integer(10)) in mydata table.
While the following solution works, I am doing type conversions since fetchall fetches 'L' and the file name tuple of nameid, cityid are strings,..
If you can suggest a pythonic or more elegant way of doing the same, that will be awesome, for me and the communtiy!
What I am trying to achieve :
Find those files from a directory that don't have a record in the database and then do something with that file, like parse/move/delete it.
MySQL table mydata :
nameid cityid
15633 45632
2354 76894
Python :
for pdffile in os.listdir(filepath):
cityid, nameid = pdffile.strip('.txt').split('_')[0], pdffile.strip('.txt').split('_')[1]
cursor.execute("select cityid, nameid from mydata")
alreadyparsed = cursor.fetchall()
targetvalues = ((str(cityid), str(nameid)) for cityid, nameid in alreadyparsed)
if (int(cityid), int(nameid)) in alreadyparsed:
print cityid, nameid, "Found"
else:
print cityid, nameid, "Not found"
I'd use a set for quick and easy testing:
cursor.execute("select CONCAT(nameid, '_', cityid, '.txt') from mydata")
present = set([r[0] for r in cursor])
for pdffile in os.listdir(filepath):
nameid, cityid = map(int, pdffile.rsplit('.', 1)[0].split('_'))
print nameid, cityid,
print "Found" if pdffile in present else "Not found"
First, I've pulled the query outside of the filename loop; no point in querying the same set of rows each time.
Secondly, I'll let MySQL generate filenames for me using CONCAT for ease of collecting the information into a set.
Thirdly, because we now have a set of filenames, testing each individual filename against the set is a simple pdffile in present test.
And finally, I've simplified your filename splitting logic to one line.
Now, if all you want is a set of filenames that are not present yet in the database (rather than enumerate which ones are and which ones are not), just use a set operation:
cursor.execute("select CONCAT(nameid, '_', cityid, '.txt') from mydata")
present = set([r[0] for r in cursor])
for pdffile in (set(os.listdir(filepath)) - present):
nameid, cityid = map(int, pdffile.rsplit('.', 1)[0].split('_'))
print nameid, cityid, "Found"
Here we use the .difference operation (with the - operator) to remove all the filenames for which there are already rows in the database, in one simple operation.
You could perform the concatenation in SQL, which will return a string:
SELECT CONCAT(nameid, '_', cityid, '.txt') FROM mydata