Python Mysql and dynamically defining fields - python

Is it possible to dynamically define the ORDER BY field through parameters? Through a relentless search, I've come up with that you can't.
So I thought I would ask if you can? Or if there is a work around to do it?
Example:
sql = "SELECT `xyz` FROM `checkins` WHERE `name`=%s AND `timestamp` >=%s AND `timestamp` < %s ORDER BY `xyz` DESC LIMIT 1"
query.execute(sql, (name, start, end))
works
sql = "SELECT `xyz` FROM `checkins` WHERE `name`=%s AND `timestamp` >=%s AND `timestamp` < %s ORDER BY `%s` DESC LIMIT 1"
query.execute(sql, (name, start, end, field))
does not work
The aim is to make the ORDER BY field dynamically defined (with the field variable), however when I do try to define dynamically, it keeps coming back with unknown field or disregarding the field because it's changing it to 'defined_field' with quotes
I have tried removing the ` from the ORDER BY as well

I am biased against %s for something like this. You could try:
name = 'kbball'
start = '2017'
end = '2018'
field = 'field'
sql = "SELECT `xyz` FROM `checkins` WHERE `name`= " + name + " AND `timestamp` >= " + start + " AND `timestamp` < " + end + " ORDER BY `"+ field + "` DESC LIMIT 1"
print(sql)
#output SELECT `xyz` FROM `checkins` WHERE `name`= kbball AND `timestamp` >= 2017 AND `timestamp` < 2018 ORDER BY `field` DESC LIMIT 1

Related

python 3.6 sql database connection

I am trying to insert a row into my postgresql database with a table created from
CREATE TABLE public.coinbase_btc_usd
(
id bigserial primary key,
price integer NOT NULL,
buy integer NOT NULL,
sell integer NOT NULL,
"timestamp" timestamp with time zone
)
However when my python 3.6 script runs and tries to add a row using psycopg2 like this it returns an error saying "no results to fetch" and nothing is added to my db.
sql_query = "INSERT INTO coinbase_btc_usd(price, buy, sell, timestamp)" \
" VALUES (" + exchange_rate + ', ' + buy_rate + ', ' + sell_rate + ", \'2015-10-10 06:44:33.8672177\')"
print(sql_query)
cur.execute(sql_query)
I also printed the sql_query variable to see exactly what was getting attempted to execute and this was printed to the output
INSERT INTO coinbase_btc_usd(price, buy, sell, timestamp) VALUES (16392.10, 16563.40, 16235.42, '2015-10-10 06:44:33.8672177')
Make sure that you are committing the transaction:
cur.execute(sql_query)
conn.commit()
Or you can enable auto commit to commit each query immediately after execution:
conn.autocommit = True
Furthermore, it costs nothing to prevent SQL injection attack - just use parametersied queries. In fact your code will actually be cleaner as well as safer:
sql_query = "INSERT INTO coinbase_btc_usd(price, buy, sell, timestamp) VALUES (%s, %s, %s, %s)"
cur.execute(sql_query, (exchange_rate, buy_rate, sell_rate, timestamp))
conn.commit()
change the
sql_query = "INSERT INTO coinbase_btc_usd(price, buy, sell, timestamp)" \
" VALUES (" + exchange_rate + ', ' + buy_rate + ', ' + sell_rate + ", \'2015-10-10 06:44:33.8672177\')"
to:
sql_query = "INSERT INTO coinbase_btc_usd(price, buy, sell, timestamp)" \
" VALUES (" + exchange_rate + ', ' + buy_rate + ', ' + sell_rate + ", \'2015-10-10 06:44:33.8672177\') returning *"
this should fix no results to fetch in my assumption.
If you see no row added, you most probably begin transaction and never commit it.

Convert MySQL query to Python

I am trying to write a SELECT query with a WHERE condition and ORDER BY.
I have the query in MySQL and would like to convert it to Python.
This is my Mysql-Query:
SELECT StoreId
, ProductCode
, TotalQuantity
FROM storeinvoicedetails
WHERE StoreId=1
ORDER BY ProductCode
This is what I tried in Python:
sql = "SELECT StoreId,ProductCode,TotalQuantity FROM storeinvoicedetails \
WHERE StoreId = '%d'" % (1) \
"ORDER BY '%s' '%s'" % ('ProductCode','ASC')
query = """SELECT StoreId,ProductCode,TotalQuantity FROM storeinvoicedetails WHERE StoreId={0} ORDER BY ProductCode ASC""".format(store_id)
> sql = "SELECT StoreId,ProductCode,TotalQuantity FROM storeinvoicedetails \
WHERE StoreId = '%d' \
ORDER BY ProductCode ASC" % id
This should work.
STOREID = 1
# make sure you add the last space for every line, otherwise it will look like 'TotalQuantityFROM' causing an error
myQuery = "SELECT StoreId,ProductCode,TotalQuantity " +
"FROM storeinvoicedetails " +
"WHERE StoreId=" + str(STOREID) + " "
"ORDER BY ProductCode"

Using (Select * from a table ) to insert data into a table

I have bottom MySql query (sql1).
sq1 = 'select course_id, creator_id, max(course_num) + 1, recordid
' from Courses where recordid in' \
' (' + ','.join(map(str, RecordMatch1)) + ') group by recordid'
cursor.execute(sql1)
BTW, RecordMatch1 is an object that has matching data from other previous queries.
I am trying to see if this is possible; (select * from sql1) portion.
sql2 = ' insert into Courses (course_id, creator_id, course_num, record_id) '\
' Values ( select * from sql1)'
cursor.execute(sql2)
Or do I have to express everything rather than using (Select * )?
What is best practice?
You can do this, but you should specify columns in case of schema changes.
Just need to confirm you are trying to run a select query and insert its output to a insert query. If that is the case this appears to be good.
yes, you can but you should do something like
sql = "SELECT course_id, creator_id, course_num, record_id FROM Courses"
all = cursor.fetchall()
for i in range(len(all))
sql1 = "INSERT INTO Courses (course_id, creator_id, course_num, record_id) VALUES (%s, %s, %s, %s)"
cursor.execute(sql1, (all[i]['Key'], all[i]['Key2'], all[i]['Key3'], all[i]['Key3']))
you can change the select like you want, remember that return a dictionary so take care about the keys, add print(all) to see what happen with the select and see the keys of each column

Trouble with SQL in python

I have this Python code:
def get_employees(conditions, fields):
cursor.execute("SELECT employeeID FROM employees WHERE name=%s, budget=%s,
%year=%s,(some of conditions))
Is there any way to get employeeIDs if I set in conditions not all parameters, etc. only name and year?
If conditions were a dictionary, you could construct a query string:
def get_employees(conditions):
query = 'select employeeid from employees'
if conditions:
query += ' where ' + ' and '.join(key + ' = %s' for key in conditions.keys())
cursor.execute(query, conditions.values())
(I should note that here I am assuming that conditions does not have user-supplied keys. If there are user-supplied keys, this is definitely vulnerable to SQL injection.)
usually it is done via dynamic sql building, like this:
sql = "SELECT employeeID FROM employees WHERE 1=1";
if condition has name
sql += " and name='" .escape(name) . "'"
if condition has somefield
sql += " and somefield='" .escape(somefield) . "'"
etc
execute final sql

PyMYSQL - Select Where Value Can Be NULL

I'm using PyMYSQL to query data from a MySQL database. An example query that I want to use is:
SELECT count(*) AS count
FROM example
WHERE item = %s
LIMTI 1
which would be run using
query = "SELECT COUNT(*) as count FROM example WHERE item = %s LIMIT 1"
cur.execute(query,(None))
or
cur.execute(query,(10))
The issue is that item can have a value of NULL which results in
WHERE item = NULL
Which doesn't work in MySQL. Rather it should read
WHERE item IS NULL
However the value can be integer also. How can I make PyMySQL adjust the query to handle both situations?
you can make a simple function to catch the None situation:
def null_for_sql(a):
return "is NULL" if not a else "= " + str(a)
and then call the query like that:
query = "SELECT COUNT(*) as count FROM example WHERE item %s LIMIT 1"
cur.execute(query,null_for_sql(None))
Note there is no "=" after "item" in the query
Edit after comments:
def sql_none_safe_generator(query,parameter):
if parameter:
return query.replace(%param, "= " + str(parameter))
else:
return query.replace(%param, is NULL)
query = "SELECT COUNT(*) as count FROM example WHERE item %param LIMIT 1"
cur.execute(sql_none_safe_generator(query,a))

Categories