Angular, Flask, mysql.connector ProgrammingError: Wrong number of arguments - python

I'm using Angular, Flask and MySQL.connector to connect to a MySQL database:
This is my python flask code handling post requests inserting a new "movie":
#app.route("/addMovies", methods=['POST'])
def addMovies():
cnx = mysql.connector.connect(user='root', database='MovieTheatre')
cursor = cnx.cursor()
insert_stmt = (
"INSERT INTO Movie (idMovie, MovieName, MovieYear) "
"VALUES (%d, %s, %d)"
)
post = request.get_json()
#data = (post['idMovie'], post['MovieName'], post['MovieYear'])
data = (100, 'Test', 2010) # test data
print(insert_stmt,data)
cursor.execute(insert_stmt,data)
cnx.commit()
cnx.close()
return data
I know its not my Angularjs, because my browser console says Internal Server Error (500) so I started printing out the insert statement handled by flask and mysql.connector:
('INSERT INTO Movie (idMovie, MovieName, MovieYear) VALUES (%d, %s, %d)', (100, 'Test', 2010))
Which seems correct.
However I keep getting
"Wrong number of arguments during string formatting")
ProgrammingError: Wrong number of arguments during string formatting
===============================================================================
Thanks to the answers, its fixed, for those wondering this is what I switched my code to :
#app.route("/addMovies", methods=['POST'])
def addMovies():
cnx = mysql.connector.connect(user='root', database='MovieTheatre')
cursor = cnx.cursor()
insert_stmt = (
"INSERT INTO Movie (idMovie, MovieName, MovieYear) "
"VALUES (%s, %s, %s)"
)
post = request.get_json()
data = (post['idMovie'], post['MovieName'], post['MovieYear'])
print(insert_stmt,data)
cursor.execute(insert_stmt,data)
cnx.commit()
cnx.close()
return data

Check the docs, it says the cursor.execute() method converts things as necessary to something the database understands. It seems you are supposed to use only %s placeholders in your string and let everything else on the execute method.

SQL parameter substitution is not the same as string formatting. You should always use %s, even for integers.

Related

I'm having trouble creating an API Post using Python flask, SQL workbench and Postman

I have a table named 'gem' in SQL Workbench and already have a working connection. When I try to add another gem using Postman, I get an error "tuple" object has no attribute 'encode'. I'm still a beginner and can't tell what I'm doing wrong. Can anyone help me?
These are my imports for the files I used. 'creds' is a file with my credentials to connect with my username and password to my db. 'sql' is the file that has the connection to MYSQL Workbench.
import flask
from flask import jsonify
from flask import request
from sql import create_connection
from sql import execute_read_query
import creds
This is my sql file for the connection the db
import mysql.connector
from mysql.connector import Error
def create_connection(host_name, user_name, user_password, db_name):
connection = None
try:
connection = mysql.connector.connect(
host=host_name,
user=user_name,
passwd=user_password,
database=db_name
)
print("Connection to MySQL DB successful")
except Error as e:
print(f"The error '{e}' occurred")
return connection
def execute_read_query(connection, query):
cursor = connection.cursor(dictionary=True)
result = None
try:
cursor.execute(query)
result = cursor.fetchall()
return result
except Error as e:
print(f"The error '{e}' occurred")
#app.route('/api/gem', methods=['POST'])
def add_example():
request_data = request.get_json()
newid = request_data['id']
newgemtype = request_data['gemtype']
newgemcolor = request_data['gemcolor']
newcarat = request_data['carat']
newprice = request_data['price']
myCreds = creds.Creds()
conn = create_connection(myCreds.conString, myCreds.userName, myCreds.password, myCreds.dbName)
sql = "INSERT INTO gem(id, gemtype, gemcolor, carat, price) VALUES(%s, %s, %s, %s, %s)", (newid, newgemtype, newgemcolor, newcarat, newprice)
gem = execute_read_query(conn, sql)
results = []
gem.append({'id': newid, 'gemtype': newgemtype, 'gemcolor': newgemcolor, 'carat': newcarat, 'price': newprice})
return 'add request successful'
cursor.execute expects either a single argument - a string - or two arguments, a string and a sequence of parameters.
sql = "INSERT INTO gem(id, gemtype, gemcolor, carat, price) VALUES(%s, %s, %s, %s, %s)", (newid, newgemtype, newgemcolor, newcarat, newprice) is a single tuple. cursor.execute recognises that it has received a single argument and tries to encode it, leading to the error.
The solution is to unpack the arguments:
cursor.execute(*query)
or pass them separately:
cursor.execute(sql_string, params)

Insert data in oracle database in python

I can't insert data into database using a dynamic query in python script
def execute_query(self, qo):
query_string = "INSERT INTO " +dep_table+ " (client, sis, entity_name_1, entity_name_2, flag_dep,process, flag_dep_det) VALUES (%s, %s, %s, %s, %s, %s, %s)" % ("'CO'","'"+qo.db_src+"'","'"+qo.table_src+"'","'"+qo.table_des+"'","'"+qo.check_func+"'","'"+qo.table_des+"'","'NULL'")+";"
cursor.execute(query_string)
I got this error:
ERROR: Failed to set dependencies informations : ORA-00933: SQL command not properly ended
The connection to the database is okay, but I can't insert.
Drop the semi-colon at the end of the string you are creating / executing.
It shouldn't be part of the SQL statement, rather used in some client tools to indicate the end of a statement so that the client can send it to the database to be executed.
I found the solution to the problem
connection.commit()
You can use format method in Python like below:
def execute_query(self, qo):
query_string = "INSERT INTO {0} (client, sis, entity_name_1, entity_name_2, flag_dep,process, flag_dep_det) VALUES ('{1}', '{2}', '{3}', '{4}', '{5}', '{6}', {7})".format(dep_table, 'CO', qo.db_src, qo.table_src, qo.table_des, qo.check_func, qo.table_des, 'NULL')
cursor.execute(query_string)

Python insert into %s MySQL

I am trying to insert some data into a database using the variable test as the table name. But unfortunately I cant seem to achieve this. Can anyone help me out?
From my raise I am getting:
TypeError: unsupported operand type(s) for %: 'tuple' and 'tuple'
My code:
test = "hello"
# Open database connection
db = MySQLdb.connect("127.0.0.1","admin","password","table" )
# prepare a cursor object using cursor() method
cursor = db.cursor()
# Prepare SQL query to INSERT a record into the database.
sql = ("""INSERT INTO %s (name,
age, gender)
VALUES (%s, %s, %s)""",(test))
try:
# Execute the SQL command
cursor.execute(sql, (name, age, gender))
db.commit()
except:
raise
db.rollback()
# disconnect from server
db.close()
I don't think MySQLdb lets you use parameters for table names -- usually this is used for actual parameters (ones that are sometimes from user input and need sanitization - the name/age/gender part gets this right). You could use Python's string formats to achieve this:
sql = ("""INSERT INTO {table} (name, age, gender)
VALUES (%s, %s, %s)""".format(table=table), (test))
Something like this will work:
sql = """INSERT INTO %s (name, age, gender)
VALUES (%s, %s, %s)""" % (test, "%s", "%s", "%s")
You need to separate Python's string substitution from MySQL's parameter substitution. The above is a crude approach, but minimally different from your own code.

PostgreSQL Schema "www" does not exist?

From the PostgreSQL documentation if you do a INSERT without specifying a schema it should be a public schema.
conn = psycopg2.connect(dbname = 'orion',
host = 'localhost',
port = 5432,
user = 'earthling',
password = 'mysupersecretpassword')
sql = conn.cursor()
def INSERT(table, info, text):
date = datetime.date.today()
query = "INSERT INTO %s (info, text, date) " \
"VALUES (%s, %s, %s)" %(table, info, text, date)
sql.execute(query)
INSERT("main", "www.capecod.edu", "test")
For some reason I'm seeing the following error?
psycopg2.ProgrammingError: schema "www" does not exist
You are using string interpolation to create the query. This is what psycopg2 executes:
INSERT INTO main (info, text, date)
VALUES (www.capecod.edu, test, 2015-09-12)
If it's not obvious what's wrong here, it's that none of the values are quoted. Here is the properly quoted version:
INSERT INTO main (info, text, date)
VALUES ('www.capecod.edu', 'test', '2015-09-12')
The error is caused by the unquoted www.capecod.edu. Due to the dots, it's being interpreted as schema.table.column.
The "right" way to do this is with a parameterized query.
query = "INSERT INTO main (info, text, date) VALUES (%s, %s, %s)"
params = (info, text, date)
sql.execute(query, params)
psycopg2 will figure out what should be quoted and how. This is a safer option than simply interpolating the string yourself, which often leaves you open to SQL injection attack.
http://initd.org/psycopg/articles/2012/10/01/prepared-statements-psycopg/
Unfortunately, you can't just toss identifiers such as the table name in as a parameter, because then they are quoted as string values, which is bad SQL syntax. I found an answer (python adds "E" to string) that points to psycopg2.extensions.AsIs as a way to pass identifiers such as table names safely as parameters. I wasn't able to make this work in my testing, though.
If you go the AsIs route, you should be cautious about checking the table names are valid, if they somehow come from user input. Something like
valid_tables = ["main", "foo", "bar", "baz"]
if table not in valid_tables:
return False

Python MySQLdb query returns error when quotes added to the arguments

I am running the following code, which gives me an error
import MySQLdb as mdb
source_sentence = "%Barack Obama%"
filterquery = ""
try:
con = mdb.connect(MYSQL_HOST, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB)
cur = con.cursor()
print "SELECT sentence_id FROM translation_all WHERE source_sentence LIKE '%s' %s ORDER BY id" % (source_sentence, filterquery)
cur.execute("SELECT sentence_id FROM translation_all WHERE source_sentence LIKE '%s' %s ORDER BY id", (source_sentence, filterquery))
uid = cur.fetchone()
print uid
except mdb.Error, e:
print "Error %d: %s" % (e.args[0],e.args[1])
sys.exit(1)
finally:
if con:
con.close()
The error is the following:
SELECT sentence_id FROM translation_all WHERE source_sentence LIKE '%Barack Obama%' ORDER BY id
Error 1064: 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 '%Barack Obama%'' '' ORDER BY id' at line 1
If I replace single quotes with double ones at the query, there is no error, but an empty query is given
SELECT sentence_id FROM translation_all WHERE source_sentence LIKE "%Barack Obama%" ORDER BY id
None
Funnily enough, both queries above, return results when executed directly on mysql through commandline or phpmyadmin. Do you have any idea why this may be failing?
When you're passing parameters to cur.execute, the dbapi already does the quoting for you. That means don't use:
... LIKE '%s' %s ORDER BY id
but
... LIKE %s ORDER BY id
You'll notice that i've removed the second %s as it's an error having it here. When it's substituted with '' the query doesn't make sense.
Don't let yourself be fooled by the string that is printed before executing the query. That isn't the query that gets executed:
"... %s" % ('spam',)
does something completely different to a query then:
cursor.execute("... %s", ('spam',))

Categories