Python - MySql.Connector UPDATE statement not working - mysql

I am having some problems with my UPDATE statement with MySQL.Connector.
My code apparently works sometimes and others not, and I don't understand why.
I made a test function, for one row, which is very similar to my other main function.
import mysql.connector
from datetime import datetime
def connect():
return mysql.connector.connect(host="xxxxx.xxx", user="xxx", passwd="xxxxxx", db="xxx")
def test():
mydb = connect()
mycursor = mydb.cursor()
sql = "SELECT MAX(value) FROM test"
mycursor.execute(sql)
date = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
for x in mycursor.fetchall():
updateSql = "UPDATE test SET date=%s WHERE value=%s"
vals = (date, x[0])
mycursor.execute(updateSql, vals)
mydb.commit()
print(vals)
print(mycursor.rowcount)
test()
This code doesn't seem to be working, as the printed rowCount value is 0.
My vals are correctly displayed : ('12-01-2020 16:47:15', 'testValue')
However, what is shown on the database is : '00-00-0000 00:00:00' .
Any ideas on how to solve this?

Edit: just found the answer.
I was using the wrong formatting.
date = datetime.now().strftime("%d-%m-%Y %H:%M:%S") wasn't properly recognized.
The DATETIME type in mySql databases requires the format to be the following:
date = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
with the Year in the first place, Month in the second one, and Day in the third one.
If this standard isn't followed then the date will be converted into 0000:00:00 00:00:00 .

Related

Python 2.7, MySQL, JSON, & DateTime - How can I remove the T between the Date and Time in the timestamp field?

I have a MySQL database with a few tables. I wrote a python script to dump some of the tables data into a JSON file. I am a bit confused with dumping the date and time stamp.
Here is the code sample, conversion.py:
import MySQLdb
import json
import collections
from datetime import date, datetime
#connect to database
conn = MySQLdb.connect(host= "localhost", user="root", passwd="root", db="testdb")
#Fetch rows
sql = "SELECT * from offices"
cursor = conn.cursor()
cursor.execute(sql)
rows = cursor.fetchall()
data = []
def json_serial(obj):
"""JSON serializer for objects not serializable by default json code"""
if isinstance(obj, (datetime, date)):
return obj.isoformat()
raise TypeError ("Type %s not serializable" % type(obj))
for row in rows:
d = collections.OrderedDict()
d['officeCode'] = row[0]
d['city'] = row[1]
d['phone'] = row[2]
d['eff_date'] = row[3]
d['lastupdatedby'] = row[4]
d['state'] = row[5]
d['country'] = row[6]
d['postalcode'] = row[7]
d['territory'] = row[8]
data.append(d)
with open('data.json', 'w') as outfile:
json.dump(data, outfile, default=json_serial)
conn.close()
When I execute this code, a JSON file is created which is fine. I have a problem with two fields, eff_date which is a date type in database and lastupdatedby is a timestamp type in the database.
"eff_date": "2015-09-23"
"lastupdatedby": "2016-08019T08:13:53"
So, in my JSON file, eff_time is created fine but lastupdatedby is getting a T in middle of date and time as shown above. But, in my actual database there is no T between the date and time. I would like to get rid of that T because I am planning to dump this file into a different database and I don't think it will accept that format.
Any help will be much appreciated.
The T between the date and time is per the ISO 8601 format.
And that's format returned by the datetime.isoformat function, found in the code here:
return obj.isoformat()
(That happens to be the format that Javascript is expecting.)
If we want to return a string different format, we probably need to use a different function, e.g. strftime function in place of isoformat.
If isoformat is working for the date objects, leave that alone. Just do the strftime for a datetime object.
The format string "%Y-%m-%d %H:%M:%S" might suit your needs.
https://docs.python.org/2/library/datetime.html#strftime-strptime-behavior

SELECT results with wrong column order with PyMySQL

I'm executing a SQL "SELECT" query on a MySQL database via python, using PyMySQL as the interface. Below is the excerpt of the code which performs the task:
try:
with self.connection.cursor() as cursor:
sql = "SELECT `symbol`,`clordid`,`side`,`status` FROM " + tablename + " WHERE `tradedate` >= %s AND (`status` =%s OR `status`=%s)"
cursor.execute(sql,(str(begindate.date()),'I','T'))
a = cursor.fetchall()
The query executes just fine. The problem is that the column ordering of the results doesn't match the order specified within the query. If I run add the following code:
for b in a:
print b.values()
The values in variable 'b' appear in the following order:
'status', 'symbol', 'side', 'clordid'
Moreover, it doesn't matter which order is specified by me- the results always appear in this order. Is there any way to fix this? Thanks in advance!
In testing I found the selected answer (convert dict to OrderedDict) to be unreliable in preserving query result column order.
#vaultah's answer in a similar question suggests using pymysql.cursors.DictCursorMixin:
class OrderedDictCursor(DictCursorMixin, Cursor):
dict_type = OrderedDict
...to create a cursor that remembers the correct column order:
cursor = conn.cursor(OrderedDictCursor)
Then get your results like normal:
results = cursor.fetchall()
for row in results:
print row # properly ordered columns
I prefer this approach better because it's stable, requires less code, and handles ordering at the appropriate level (as the columns are read).
I amolst sure you need collections.OrderedDict, as each table row is a dict where keys stays for columns:
# python 2.7
import pymysql.cursors
from collections import OrderedDict
# ...
results = cursor.fetchall()
for i in results:
print OrderedDict(sorted(i.items(), key=lambda t: t[0]))
Also, based on your code snippet b.values() sounds like SQL ORDER BY col_name ASC|DESC. On this case SQL should be work pretty well.
Since you liked that solutuion
Here is an approach:
with self.connection.cursor() as cursor:
sql = "SELECT `symbol`,`clordid`,`side`,`status` FROM " + tablename + " WHERE `tradedate` >= %s AND (`status` =%s OR `status`=%s)"
cursor.execute(sql,(str(begindate.date()),'I','T'))
a = cursor.fetchall()
for b in a:
print "%s, %s, %s, %s" % (b["symbol"], b["clordid"], b["side"], b["status"])
I am not sure, if I should post this answer or to flag your OP to be closed as a duplicate.

How to use Django ORM to function on a field

This question is a follow-up to this one.
I'm running a Django application on top of a MySQL (actually MariaDB) database.
My Django Model looks like this:
from django.db import models
from django.db.models import Count, Sum
class myModel(models.Model):
my_string = models.CharField(max_length=32,)
my_date = models.DateTimeField()
#staticmethod
def get_stats():
logger.info(myModel.objects.values('my_string').annotate(
count=Count("my_string"),
sum1=Sum('my_date'),
sum2=Sum(# WHAT GOES HERE?? #),
)
)
When I call get_stats, it gives me the count and the sum1.
However, for sum2, I want the sum of the following Database expression for each matching row: my_date + 0 (this converts it to a true integer value).
What should I put in the expression above to get that sum returned in sum2?
When I change it to sum2=Sum(F('my_date')), I get the following exception: http://gist.github.com/saqib-zmi/50bf572a972bae5d2871
Not sure, but try F() expression
from datetime import timedelta
myModel.objects.annotate(
count=Count("my_string"),
sum1=Sum('my_date'),
sum2=Sum(F('my_date') + timedelta(days=1))
).values('my_string', 'count', 'sum1', 'sum2')
https://docs.djangoproject.com/en/dev/ref/models/queries/#f-expressions

sqlalchemy update column with an expression

I want to update a row setting the result of an expression on a column, ex:
MyTable.query.filter_by(id=the_id).update({
"my_col": "(now() at time zone 'utc')"
})
This code give me the following error :
(DataError) invalid input syntax for type timestamp: "(now() at time zone 'utc')"
LINE 1: ...12bf98a-1ee9-4958-975d-ee99f87f1d4a', my_col='(now() at...
^
'UPDATE my_table SET my_col=%(redeemed_at)s WHERE id = %(id_1)s' {'my_col': "(now() at time zone 'utc')",
this should translate in sql to :
update my_table set my_col = (now() at time zone 'utc') where id = ?;
this SQL statement works when run from the console
You can use this syntax with sqlalchemy func object, as the following code:
from sqlalchemy.sql.expression import func
# get a sqlalchemy session
session.query(YourTable).filter_by(id=the_id).update(values={'my_col': func.utc_timestamp()}, synchronize_session=False)
session.commit()
The error is because the timestamp cannot be a string that is "(now() at time zone 'utc')"
You could try using the Text() function or func.now() or to get the time in UTC
db.func.timezone('utc', db.func.now())
EDIT:
You can try using synchronize_session as 'evaluate' or,
Since you are only updating one row, you can just do this:
mytable_row_obj = MyTable.query.filter_by(id=the_id).one()
mytable_row_obj.my_col = ... What ever you want to put here ...
session.commit()

MySQL-python: SELECT returns 'long' instead of the query

I'm having a problem with running a select query, using mysql-python, on an established database. The issue is that a number, what Python refers to as a long, is returned instead of the data queried- it should be noted that this number corresponds to the number of records which should be returned (I logged into the database and ran the query from MySQL to make sure).
Here is the code:
db = MySQLdb.connect(db = 'testdb', user='testuser', passwd='test', host='localhost', charset='utf8', use_unicode=True)
dbc = db.cursor()
result = dbc.execute("""SELECT %s FROM example_movie""", ('title',))
urls = [row[0] for row in result]
The last bit of code, urls = [row[0] for row in result] is to put everything into a list.
The error looks like this:
TypeError: 'long' object is not iterable
When I have python print result it returns:
('RESULT:', 52L)
When I enclose result like str(result) it just returns the number 52 (not long)
Any help and suggestions are greatly appreciated!
The return value from dbc.execute is not the results of the select; I believe it is the number of rows in the results. In order to get the actual results you need to call one of the fetch methods. See documentation here.
You should update your code to read:
db = MySQLdb.connect(db = 'testdb', user='testuser', passwd='test', host='localhost', charset='utf8', use_unicode=True)
dbc = db.cursor()
row_count = dbc.execute("""SELECT title FROM example_movie""")
results = dbc.fetchall()
urls = [row[0] for row in result]