I was using sqlite however moved to MySqL
Sqlite code that worked:
#app.route('/api/v1/users/user', methods=['GET'])
def api_filter():
query_parameters = request.args
userid = query_parameters.get('userid')
username = query_parameters.get('username')
query = "SELECT * FROM tblUser WHERE"
to_filter = []
if userid:
query += ' user_id=? AND'
to_filter.append(userid)
if username:
query += ' username=? AND'
to_filter.append(username)
if not (userid or username):
return page_not_found(404)
query = query[:-4] + ';'
conn = sqlite3.connect('dbApp.db')
conn.row_factory = dict_factory
cur = conn.cursor()
results = cur.execute(query, to_filter).fetchall()
return jsonify(results)
Now when I change it to MySQL it does not work:
#app.route('/api/v1/users/user', methods=['GET'])
def api_filter():
query_parameters = request.args
userid = query_parameters.get('userid')
username = query_parameters.get('username')
query = "SELECT * FROM tblUser WHERE"
to_filter = []
if userid:
query += ' user_id=? AND'
to_filter.append(userid)
if username:
query += ' username=? AND'
to_filter.append(username)
if not (userid or username):
return page_not_found(404)
query = query[:-4] + ';'
conn = mysql.connector.connect(host="localhost", user="root", password="green", database="dbApp")
conn.row_factory = dict_factory
cur = conn.cursor()
results = cur.execute(query, to_filter).fetchall()
return jsonify(results)
The error returned:
results = cur.execute(query, to_filter).fetchall()
File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/mysql/connector/cursor_cext.py", line 260, in execute
raise errors.ProgrammingError(
mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement
127.0.0.1 - - [28/Dec/2020 17:47:11] "
This is after running:
http://127.0.0.1:5000/api/v1/users/user?userid=3&username=Jo
http://127.0.0.1:5000/api/v1/users/user?userid=3
http://127.0.0.1:5000/api/v1/users/user?username=Jo
Also added this:
from flask import request, jsonify
import mysql.connector
Here is what the documentation says:
cursor.execute(operation, params=None, multi=False)
This method executes the given database operation (query or command).
The parameters found in the tuple or dictionary params are bound to
the variables in the operation. Specify variables using %s or %(name)s
parameter style (that is, using format or pyformat style). execute()
returns an iterator if multi is True.
I think there are two problems with your code: you are using ? for bind variables instead of %s, and you are passing in a list instead of a tuple. Alternatively use named parameters and pass in the values with a dict. Try both and see what you like most.
user_id = %s" and to_filter = (userid, ). You can use the list you have now and just convert it with tuple().
" user_id = %{user_id}" and set to_filter = {'user_id': userid }.
It is cleaner to build a list of conditions, then ' AND '.join(conditions) instead of removing the extra AND. You can simplify the code a little bit by just leaving out the ';'.
Related
I'm using tuple to set params in sql query but it converts str params to int. I need the params keep being a string.
From a function I create a query using .sql file.
My .sql file is something like that:
update table t
set t.status = %s
where t.id in (%s)
My function to create a query from file is:
def create_query(where=[]):
path = f'./file.sql'
with open(path, 'r') as file:
query = file.readlines()
return ' '.join(query)
return None
I call my function from this way passing the parameters:
status = 'CREATED'
ids = ('123', '1324', '124512')
params = list([ status, ids ])
query = create_query() % tuple(params)
I get a query like this:
update table t set t.status = CREATED where t.id in (22457, 22458,
22459)
I would like to do the interpolation keeping the quotations marks.
So, the query should look like this:
update table t set t.status = 'CREATED' where t.id in (22457, 22458,
22459)
If I do this:
status = ('CREATED',)
ids = ('123', '1324', '124512')
params = list([ status, ids ])
query = create_query() % params
I get this:
update table t set t.status = ('CREATED',) where t.id in (22457, 22458, 22459)
And it doesn't work for errors in my sql (comma in status).
I'm using sqlalchemy
I solved the problem modifying my .sql file adding single quote.
update table t
set t.status = '%s'
where t.id in (%s)
One approach here is to generate the IN clause with the correct number of placeholders based on the number of values. For example:
status = ('CREATED',)
ids = ('123', '1324', '124512',)
params = status + ids
where = '(%s' + ',%s'*(len(ids) - 1) + ')'
sql = 'update some_table t set t.status = %s where t.id in ' + where
cursor.execute(sql, params)
You can use ? in the query so the parameters are replaced by sql and you don't have to worry about the quotes:
status = ('CREATED',)
ids = (123, 1324, 124512, 33333, 44444)
params = status + ids
sql = f'update t set status = ? where id in (?{", ?"*(len(ids)-1)});'
cursor.execute(sql, params)
asuming id is INT
I am trying to update a SQL Table given a users input I have the following code. The user can choose to enter in/change the below fields which are defaulted to the values in the SQL table. However when I run the code I get the following error message
mysql.connector.errors.ProgrammingError: Not enough parameters for the SQL statement
I have counted it many times and it seems like the %s match the passed parameters. Am I missing something?
user = User_name_body.get('1.0',END)
passw = Password_text.get('1.0',END)
first = First_name.get('1.0',END)
last = Last_name.get('1.0',END)
phone = Phone_number.get('1.0',END)
email = Email_address.get('1.0',END)
mycursor = mydb.cursor()
sql = "UPDATE t_users SET Email_address=%s, First_name=%s, Last_name=%s, Phone_Number=%s, Password=%s WHERE User_Name=%s VALUES(%s,%s,%s,%s,%s,%s)"
val = (email, first, last, phone, passw,user)
mycursor.execute(sql, val)
mydb.commit()
mydb.close()
UPDATE does not take VALUES, you should change your sql query line to look like this:
sql = "UPDATE t_users SET Email_address=%s, First_name=%s, Last_name=%s, Phone_Number=%s, Password=%s WHERE User_Name=%s"
Python throws an error because you are asking for 12 parameters and only providing 6.
Prepare your sql data like this:
sql = """ UPDATE t_users SET Email_address=%s, First_name=%s, Last_name=%s, Phone_Number=%s, Password=%s WHERE User_Name = %s """
val = (email, first, last, phone, passw, user)
mycursor.execute(sql, val)
or you can do it like this
sql = "UPDATE btms_users SET btms_users.user='%s', btms_users.secret='%s' , btms_users.first_name='%s', " \
"btms_users.second_name='%s', btms_users.email='%s', btms_users.mobile='%s' " \
"WHERE btms_users.id='%s'" % (user_name, user_secret, user_firstname, user_lastname,
user_email, user_phone, user_id)
mycursor.execute(sql)
and here is a full working example:
import mysql.connector
mydb = mysql.connector.connect(
host="localhost",
user="root",
password="test",
database="test"
)
mycursor = mydb.cursor()
sql = "UPDATE items SET name = %s WHERE id = %s"
val = ("Test", 1)
mycursor.execute(sql, val)
mydb.commit()
print(mycursor.rowcount, "record(s) affected")
my_connect = mysql.connector.connect(
host="localhost",
user="xyz",
passwd="xyz",
database="tracking"
)
my_conn = my_connect.cursor()
x = input("enter name")
query="SELECT * FROM trackingtable WHERE Customer_Name = \"x\"";
print(query)
my_conn.execute(query)
my_conn.close()
Query printed statement
How do i get the proper query using the input from user? I tried using placeholders but I couldn't get them to work
Try:
query = f"SELECT * FROM trackingtable WHERE Customer_Name = {x}"
It's an f-string in which you can plug in variables via {}.
If you need the "s inside the query:
query = f'SELECT * FROM trackingtable WHERE Customer_Name = "{x}"'
Do you need the ; at the end?
I am using Python 3.6 with Flask. I am trying to connect to Amazon Redshift database using SqlAlchemy. The query has IN operation in the Where clause and the values for it are sent by binding it to the query. For some reason it does not work? It does not error out, but does not fetch any results. If I hard code the values in the query, it works fine.
I have tried a few suggested options but no luck -
1. binding the values as a list or just as comma separated string
2. removing the brackets in the query
3. changing the code to
stmt = text(file.read())
stmt = stmt.bindparams(search = ids)
df = pd.read_sql_query(stmt, connection)
dtv_script.txt
Select * from tbl1 where id IN (:search)
def get_dt(id_list):
engine = create_engine('postgresql://xxxxxxxxxx')
connection = engine.connect()
ids = list(id_list.split(","))
#dtv_script.txt has the sql
file = open('dtv_script.txt')
sql = text(file.read())
df = pd.read_sql_query(sql, connection, params={'search' : ids})
connection.close()
return df
The ids are posted from a form on the index.html.
Sample ids = 2011592,2021593,2033591.
The flask route page captures it in the get_dt() function and returns the dataframe back to the results.html page for display
#app.route('/result', methods=['POST'])
def result():
if request.method == 'POST':
id_list = request.form.get('ids')
df_dt = dofri.get_dt(id_list)
return render_template('result.html', **locals())
else:
flash('There was some error. Check the logs')
return index()
Below is the solution. Make sure to
add - from sqlalchemy import bindparam
remove - brackets from the query
add - expanding=True
dtv_script.txt
Select * from tbl1 where id IN :search
def get_dt(id_list):
engine = create_engine('postgresql://xxxxxxxxxx')
connection = engine.connect()
ids = list(id_list.split(","))
#dtv_script.txt has the sql
file = open('dtv_script.txt')
sql = file.read()
t = text(sql)
t = t.bindparams(bindparam('search', expanding=True))
df = pd.read_sql_query(t, connection, params={'search' : ids })
connection.close()
return df
When I try to pass a tuple to the IN argument of a WHERE clause, it gets double-quoted so my query fails. For example, if I do this,
# Connect to DB
import MySQLdb
cnxn = MySQLdb.connect(connectString)
curs = cnxn.cursor()
# Setup query
accounts = ('Hyvaco','TLC')
truck_type = 'fullsize'
query_args = (truck_type, accounts)
sql ='SELECT * FROM archive.incoming WHERE LastCapacity=%s AND Account IN %s'
# Run query and print
curs.execute(sql, query_args)
print(curs._executed)
then I get zero rows back, and the query prints out as
SELECT * FROM archive.incoming WHERE LastCapacity='fullsize'
AND Account IN ("'Hyvaco'", "'TLC'")
Switching accounts from a tuple to a list does not affect the result. How should I be passing these arguments?
How about you create the accounts as a string and then do this:
accounts = "('Hyvaco','TLC')"
sql ='SELECT * FROM archive.incoming WHERE LastCapacity=%s AND Account IN '+ accounts