pyodbc UPDATE throws an exception - python

I'm making a python program that does Elo calculations for an Azure SQL database. The problem is with the last two 'cursor.execute' commands (the UPDATEs).
I took out part of the code before posting here to make it smaller, but all the variables are properly passed from the find_winner and find_loser methods-- the print commands show the right value.
When I run the program as is, it prints the change in ratings and the message from the except block. When I comment out the UPDATE methods, it doesn't print the except message. The only reason I can come up with is that the variables from the tuple from find_winner and find_loser aren't being entered into the SQL statement properly.
I tried running it with ? and '%s' instead of winner_new_rating and winner_id, but none of the 3 versions worked.
Is there something obvious I'm missing? What's the proper way of entering parameters stored in variables?
def rate():
try:
(winner_rating,winner_name,winner_id) = find_winner()
(loser_rating,loser_name,loser_id) = find_loser()
cursor = conn.cursor()
print(winner_name, "wins", winner_rating, "-->", winner_new_rating)
print(loser_name, "loses:", loser_rating, "-->", loser_new_rating)
cursor.execute("UPDATE KIDS SET Rating = winner_new_rating WHERE LocalID = winner_id")
cursor.execute("UPDATE KIDS SET Rating = loser_new_rating WHERE LocalID = loser_id")
conn.commit()
except:
print("Rate method error")

This is the correct syntax:
try:
cursor.execute("UPDATE KIDS SET Rating = ? WHERE LocalID = ?",
str(winner_new_rating), winner_id)
cursor.execute("UPDATE KIDS SET Rating = ? WHERE LocalID = ?",
str(loser_new_rating), loser_id)
except DatabaseError as e:
print(str(e))

Related

why do Syntax error (python) doesn't work?

I want to print a message in case the user made a mistake while writing the code but it doesnt work I also tried to add NameError exception, it only works if I raise an exception.Thank you for helping.
`
def cncours(nvcours,num_cours):
try :
sql="Update cours set nomC=%s where num_cours=%s"
result=cursor.fetchone()
cursor.execute(sql,(nvcours,num_cours))
print("Operation Done.")
except TypeError:
print("Plz put the name between quotes")
`
Each DB implementation (MySQL, sqlite,...) may raise their particular exceptions. So instead of catching a general exceptions, you may catch errors depending on the specific DB, then on the particular type (e.g. SyntaxError). I suggest to provoque a syntax error on your SQL statement then see what type is (e.g. errorcode or exception type) then catch it.
For instance, the MySQL connector raises error numbers:
import mysql.connector as cn
try:
#...
except cn.Error as err:
print("Something went wrong: {}".format(err))
if err.errno == errorcode.ER_BAD_TABLE_ERROR: #
Here are some MySQL Error Code Ranges
If you are using MySQLdb:
import MySQLdb
try:
#...
cursor.execute(sql)
res = cursor.fetchone()
# ...
except MySQLdb.Error, e:
print "MySQLdb.Error: {}".format(e.args)
Depending on your schema (column types) and the type from the input variable, you may use:
sql="Update cours set nomC='%s' where num_cours=%s" # Added quotes on the first replacement
Besides what you are asking, I think that the command order is inverted.
sql="Update cours set nomC=%s where num_cours=%s"
cursor.execute(sql,(nvcours,num_cours)) # First
result=cursor.fetchone() # Second
print("Operation Done.")
https://www.tutorialspoint.com/python/python_database_access.htm
# execute SQL query using execute() method.
cursor.execute("SELECT VERSION()")
# Fetch a single row using fetchone() method.
data = cursor.fetchone()

How to insert variable to database table sqlite3 - Python

Whenever i try to run the following code i get an error saying that theres no such column "title_data", im really confused because "TITLE" is the column not "title_data"
def insertData(self):
title_Data = self.edit_title.text()
year_Data = self.edit_year.text()
rating_Data = self.edit_rating.text()
connection = sqlite3.connect('films.db')
try:
connection.execute("INSERT INTO FILMS (TITLE,YEAR,RATING) VALUES(title_Data,year_Data,rating_Data)")
except sqlite3.IntegrityError:
print("You have already stored this data")
connection.commit()
connection.close()
You're not passing your variables correctly. Instead of
connection.execute("INSERT INTO FILMS (TITLE,YEAR,RATING) VALUES(title_Data,year_Data,rating_Data)")
You should use
connection.execute("INSERT INTO FILMS (TITLE,YEAR,RATING) VALUES(?,?,?)", (title_Data,year_Data,rating_Data))
See the docs for execute() for more information.

SQL query works in console but not in python

Hi im having issues with a sql query it works perfect in console, but when i implement into python it seems to work perfect no errors but when i check the database it hasnt worked, yet with the console it does work the same no errors yet when i check db the data is there... exact same query i use.
Any ideas?
UPDATE ex SET fbsiteurl = stringvarible, fbsitesource = '' WHERE id = 23123;
in python:
cur = con.cursor()
sqlquery = "UPDATE ex SET fbsiteurl = '"+somevarible+"', fbsitesource = '"+somevarible+"' WHERE id = %d;" % recordid
print sqlquery
cur.execute(sqlquery)
query shows up fine in print no issues, if i copy the print out and paste it into a mysql console it works perfect everytime, just come python it acts like it works but dosnt really 0_o
connection.autocommit(), or you need to do connection.commit()
Been there :) you need to close the cursor
This little gotcha continues to this day. Just to clarify, I had to use both of the above answers, as in:
cur = self.db.cursor()
try:
cur.execute(sqlcommand)
self.db.commit()
res = cur.fetchall()
except res is not None:
print(res)
finally:
cur.close()

Python-mysql: when to explicitly rollback a transaction

Suppose, I have a modifying statement:
cursor = conn.cursor()
# some code
affected_rows1 = cursor.execute(update_statement1, params1)
# some code
conn.commit()
cursor.close()
Should I wrap the block of code with a try ... except and explicitly rollback a transaction when an exception is raised, and which MySQLdb exceptions should I catch to rollback? I used to catch any StandardError in this case, but now I have a hesitation that the block of code would even need an explicit rollback at all.
The following example is slightly more difficult, and I understand that it does require an explicit rollback if the first update statement succeeded. Still, which exceptions should I catch in this case:
cursor = conn.cursor()
# some code
affected_rows1 = cursor.execute(update_statement1, params1)
# some code
affected_rows2 = cursor.execute(update_statement2, params2)
#some code
conn.commit()
cursor.close()
This link shows the various types of Errors that you can catch. MySQLdb.Error is the standard base class from which all other MySQL Errors are derived.
I usually use MySQLdb.Error because it lets you focus on errors relating to MySQLdb itself. By contrast StandardError will catch almost all the exceptions (not something you want if you want better debugging capability). Plus the use of MySQLdb.Error allows you to display the exact error message (MySQL error number and all) so that you can debug it faster.
Coming to the first part of the question, in case of database statements it is (usually) necessary to rollback transactions (if they are supported) in case of error.
The methodology that I follow is to wrap each execute statement in a try except clause (catching MySQLdb.Error) and using rollback if there is an an error before printing the error message and exiting.
However, there is a catch. In MySQLdb the changes that you make to DB are not actually written to the database until you explicilty call commit. So, logically, rollback is not necessary.
As an example,
conn = MySQLdb.connection(db=, host=, passwd=, user=)
cur = conn.cursor()
#Say you have a table X with one entry id = 1 and total = 50
cur.execute("update X set total = 70 where id = 1")
#Actual DB has not yet changed
cur.execute("update X set total = 80 where id = 1")
#Actual DB has still not changed
If you exit the program without commiting, the value in DB will still be 50 because you never called commit().
This is how you would ideally do it:
conn = MySQLdb.connection(db=, host=, passwd=, user=)
cur = conn.cursor()
#Say you have a table X with one entry id = 1 and total = 50
try:
cur.execute("update X set total = 70 where id = 1")
except MySQLdb.Error,e:
print e[0], e[1]
conn.rollback()
cur.close()
conn.close()
#print lengthy error description!!
sys.exit(2)
#Note: Value in table is still 50
#If you do conn.commit() here, value becomes 70 in table too!!
try:
cur.execute("update X set total = 80 where id = 1")
except MySQLdb.Error,e:
print e[0], e[1]
conn.rollback()
cur.close()
conn.close()
#print lengthy error description!!
sys.exit(2)
#Value in DB will be
#a) 50 if you didn't commit anywhere
#b) 70 if you committed after first execute statement
conn.commit()
#Now value in DB is 80!!
cur.close()
conn.close()
IMHO, you should rollback transactions if you continue to use the same connection. Else everything before the error will get commit when you finish the transactions.
For the exception to catch, I always use MySQLdb.Error but I'm not sure that's correct.
Its advised to wrap execute() in a sub. This is how i do it.
def executeSQL(self, stmt):
cursor = self.dbHand.cursor()
if not stmt.endswith(";"):
stmt += ';'
try:
cursor.execute(stmt)
except MySQLdb.Error, e:
self.logger.error("Caught MYSQL exception :%s: while executing stmt :%s:.\n"%(e,stmt))
return False

Mysqldb Update error with set %s

I have created a database with MySQLdb.
In database I have a table with name student with columns:
id(is int),
id_user(is int),
f_name(is str),
l_name(is str)
I want to update a row.
My code is below:
db=mdb.connect(host="localhost", use_unicode="True", charset="utf8",
user="", passwd="", db="test")
# prepare a cursor object using cursor() method
cursor = db.cursor()
sql="""SELECT id_user FROM student"""
try:
# Execute the SQL command
cursor.execute(sql)
# Commit your changes in the database
db.commit()
except:
# Rollback in case there is any error
db.rollback()
rows = cursor.fetchall()
the=int(7)
se=str('ok')
for row in rows:
r=int(row[0])
if r==the:
sql2 = """UPDATE student
SET f_name=%s
WHERE id_user = %s"""% (se,the)
# Execute the SQL command
cursor.execute(sql2)
# Commit your changes in the database
db.commit()
db.rollback()
# disconnect from server
db.close()
When I run it I take the error there is column with name ok why?
Can anyone help me find what I am doing wrong please?
str doesn't wrap its argument in quotation marks, so your statement is this:
UPDATE student SET f_name=ok WHERE id_user = 7
when it needs to be this:
UPDATE student SET f_name='ok' WHERE id_user = 7
So, either change this line:
SET f_name=%s
to this:
SET f_name='%s'
or else change this line:
se=str('ok')
to this:
se="'" + str('ok') + "'"
Though I recommend reading about SQL injection, which will become a concern as soon as you start using user-supplied data instead of hard-coded values.
You should run the query like this:
sql2 = """UPDATE student
SET f_name = %s
WHERE id_user = %s"""
cursor.execute(sql2, (se, the))
Don't use string interpolation, let the database driver handle passing the parameters for you. Otherwise you have to deal with syntax errors like this, or worse, SQL injection.
More details here.
You should always enclose your data with quotes.
Instead of %s solely use '%s' the only types you dont need it are numeric ones, but even there i would enclose %d with '%d' cos it is more save.
And you should use at least db.escape_string(your_data) before inserting or updating same values into your database.
Or have a look at the pdo-using style of mysqldb:
http://mysql-python.sourceforge.net/MySQLdb.html#some-examples
c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
WHERE price < %s""", (max_price,))

Categories

Resources