InternalError: (1054, u"Unknown column 'Ihe' in 'where clause'") - python

Below is a part of my python/pymysql code. I'm basically trying to retrieve data from a database using the input typed into a search box. I don't understand why the data typed in is coming across with this error. "Ihe" is simply a test hostname in my the database.
#app.route('/result',methods= ['POST', 'GET'])
def result():
if request.method == 'POST':
result = request.form['hostname']
cursor = connection.cursor()
query = ("SELECT * FROM StoryData WHERE hostName LIKE %s" % ( result))
cursor.execute(query)
search_for = cursor.fetchall()
for row in search_for:
ID = row['ID']
hName = row['hostName']
rName = row['reportName']
return render_template("result.html", search_for=search_for)
connection.close()

As written, this is a very dangerous SQL Injection vulnerability.
What happens when I submit a POST request with hostname set to
''; DROP TABLE StoryData;
?
Use parameterized queries instead of using Python string formatting. Assuming your paramstyle is format, you can pass the parameters to execute():
query = "SELECT * FROM StoryData WHERE hostName LIKE %s"
cursor.execute(query, (result, ))

Related

Cannot insert integer to MySQL in python

In my flask application, I cannot insert user_id which I get from request.form
and it is an integer to MySQL. Here is my code:
from flask import Flask, jsonify, render_template
from flask import request
import socket
from flask_mysqldb import MySQL
app = Flask(__name__)
app.config['MYSQL_HOST'] = '192.168.0.101'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PORT'] = '3307'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'msblog_users'
mysql = MySQL(app)
#app.route("/create_post", methods = ['POST', 'GET'])
def create_post():
if request.method == 'GET':
return "You can only send post requests here!"
if request.method == 'POST':
user_id = request.form.get('user_id')
message = request.form.get('message')
cursor = mysql.connection.cursor()
cursor.execute('''INSERT INTO posts (user_id, post)VALUES (%s, %s)''', (int(user_id), message))
mysql.connection.commit()
cursor.close()
return "Done"
I get the following error:
TypeError: 'str' object cannot be interpreted as an integer
What should I do? I did lots of search but so far nothing!
The error comes from the int(user_id) part, specifically due to the value being None. You should first make sure it is a valid integer:
try:
user_id = int(request.form.get('user_id'))
except (ValueError, TypeError):
return <error 400>
The %s stands for string, if you want you want that parameters to be an integer, make it %i.
INSERT INTO posts (user_id, post)VALUES (%i, %s) ....
If the column post is a string / text column (varchar probably) you should also quote it as such.
cursor.execute("INSERT INTO posts (user_id, post) VALUES (%i , '%s')" % (1, 'string value')
By the way, this is the old way of formatting strings
The new way is doing this:
cursor.execute("INSERT INTO posts (user_id, post) VALUES ({}, '{}')".format(1, 'string value')
Or you can name the parameters:
"INSERT INTO posts (user_id, post) VALUES ({id}, '{str}')".format( str='string value',id=1)
Finally, I found the problem.
It's so strange!! the problem was not even related to the insert query. Take a look at the MySQL connection configuration part in my flask code, as you can see below:
app.config['MYSQL_HOST'] = '192.168.0.101'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PORT'] = '3307'
app.config['MYSQL_PASSWORD'] = 'password'
app.config['MYSQL_DB'] = 'msblog_users'
the port is written between quotations! it's a string but MySQL needs an integer value for the port to be able to connect!
here is the quick fix:
app.config['MYSQL_PORT'] = 3307
It took me a day to solve it!

Transfering Data in MS Access Using Python

I have an ever growing and changing database that reflects a permits passed by the State and EPA.
As the database changes and updates I need to transfer the relevant information.
The script does two things; first it checks which fields are the same and creates a list of fields and data that will be inserted into the new database. Second to insert the data into the new database.
Problem is I cannot get it to insert. I have matched everything like it says online in various ways but i get error ('42000', '[42000] [Microsoft][ODBC Microsoft Access Driver] Syntax error in INSERT INTO statement. (-3502) (SQLExecDirectW)').
I cannot figure out how to prevent it.
Code:
import pyodbc
importDatabase = r"J:\ENVIRO FIELD\AccessDatabases\MS4\MS4 Town Databases\~Template\MS4_Apocalypse Import DEV 1.accdb"
"Create the Import Database Connection"
connectionImport = pyodbc.connect(r'Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=%s;' %(importDatabase))
cursorImport = connectionImport.cursor()
"####---Outfall Section---####"
"Import the outfall names into the new database"
tbl = "tbl_Outfall_1_Profile"
exportList = []
importList = []
for row in cursorImport.columns(table = "tblExportMigration_Outfall_1_Profile"):
field = row.column_name
exportList.append(field)
for row in cursorImport.columns(table = "tbl_Outfall_1_Profile"):
field = row.column_name
importList.append(field)
matchingList = []
for field in exportList:
if field != "outfallID":
if field in importList:
matchingList.append(field)
else:
continue
sqlValue = ""
for field in matchingList:
sqlValue += "[%s], " %(field)
sqlValue = sqlValue[:-2]
sql = "SELECT %s from %s" %(sqlValue, "tblExportMigration_Outfall_1_Profile")
for rowA in cursorImport.execute(sql):
tupleList = list(rowA)
tupleList = ["" if i == None else i for i in tupleList]
tupleValues = tuple(tupleList)
sqlUpdate = """INSERT INTO tbl_Outfall_1_Profile (%s) Values %s;""" %(sqlValue, tupleValues)
cursorImport.execute(sqlUpdate)
cursorImport.close()
This is the sql string I create
"INSERT INTO tbl_Outfall_1_Profile ([profile_OutfallName], [profile_HistoricalName1], [profile_HistoricalName2], [profile_HistoricalName3], [profile_HistoricalName4]) Values ('756', '', '', '', '');"
Taking what #Gord Thompson said I was actually able to create a dynamic parameter flow
First created a module to create the ?
def Defining_Paramters(length):
parameterString = ""
for x in range(1,length):
parameterString += "?, "
parameterString += "?"
return parameterString
Then stuck it into the string for the sql update
sqlUpdate = sqlUpdate = "INSERT INTO %s (%s) Values (%s);" %(table, sqlFrameworkSubStr, parameters)
Run the cursor and commit it
cursorTo.execute(sqlUpdate, (dataTuple))
connectionTo.commit()
It would seem that you have to create the query in its entirety then have your data in tuple format for entry
This is the sql string [I think] I create
Try this:
sqlUpdate = """INSERT INTO tbl_Outfall_1_Profile (%s) Values (%s);""" %(sqlValue, tupleValues)
or perhaps:
sqlUpdate = "INSERT INTO tbl_Outfall_1_Profile (%s) Values (%s);" %(sqlValue, tupleValues)

retrieving data from table based on a value from a python variable

I am writing a function that will retrieve data from sqlite table based on the parameters user provide. This is the function so far
def database_retrieve(db_file, id):
try:
conn = sqlite3.connect(db_file)
with conn:
sql_command = "SELECT * FROM my_table WHERE id = "+id
cur = conn.cursor()
cur.execute(sql_command)
result = cur.fetchall()
return result
except Exception as e:
print(e)
db_file = 'testdb.db'
print(database_retrieve(db_file, 'subject1'))
This gives me the following error
no such column: subject1
None
When I add subject1, which is an entry under the id column in my_table, directly to the sql command like this
sql_command = "SELECT * FROM my_table WHERE id = 'subject1'"
it works fine and prints all the data.
I am new to sqlite3. Please help. Thanks in advance
These are the links I used to come this far
Python sqlite3 string variable in execute
https://www.dummies.com/programming/databases/how-to-retrieve-data-from-specific-rows-in-mysql-databases/
When you do this
sql_command = "SELECT * FROM my_table WHERE id = "+id
The value of sql_command is
"SELECT * FROM my_table WHERE id = subject1"
As you can see, subject1 is not in quotes. sqlite thinks it is a column, that's why you see that error.
Instead, do this
sql_command = "SELECT * FROM my_table WHERE id = ?"
cur.execute(sql_command, [id])
? acts as a placeholder for the variable id.
The official sqlite3 documentation mentions few others methods
https://docs.python.org/2/library/sqlite3.html
The sql_command string being generated should be something like this (Formatted string):
sql_command = "SELECT * FROM my_table WHERE id = %s AND name = %s" % (212212, 'shashank')

Sybpydb error 5701 ignored sometimes

I have come across a very strange behavior when developing an application in Python (2.7.11) using a Sybase ASE 15.7 database and the sybpydb library.
When selecting data from the database there is always an error 5701 thrown that isn´t an error but just a informational message taht the client has logged on or changed database.
This should be ignored by the client and it works fine most of the time but sometimes not.
Has anyone come across this problem and know a way to work around it?
I don´t want to stop handling exceptions.
The following code illustrates the problem, the first two queries runs as the should but the last one doesn´t work, I have checked the query and yes it returns a result set.
uname = 'username'
pwd = 'password'
server = 'server'
conn = sybpydb.connect(user=uname, password=pwd, servername=server)
cur = conn.cursor()
try:
sql = 'select * from database..table1'
cur.execute(sql)
print 'Execute for table1'
print cur.connection.errors()
row = cur.fetchone()
print "Query Returned %d row(s)" % cur.rowcount
print row
except sybpydb.Error:
print cur.connection.errors()
finally:
cur.close()
conn.close()
conn = sybpydb.connect(user=uname, password=pwd, servername=server)
cur = conn.cursor()
parameter1 = 'DSE'
try:
sql = 'select * from database..table2 where column1 = ?'
cur.execute(sql, [parameter1])
print 'Execute for table2'
print cur.connection.errors()
row = cur.fetchone()
print "Query Returned %d row(s)" % cur.rowcount
print row
except sybpydb.Error:
print cur.connection.errors()
finally:
cur.close()
conn.close()
parameter1 = 1
parameter2 = 1
conn = sybpydb.connect(user=uname, password=pwd, servername=server)
cur = conn.cursor()
try:
sql = 'select * from database..table3 where column1 = ? and column2 ?'
cur.execute(sql, [parameter1, parameter2])
print 'Execute for table3'
print cur.connection.errors()
row = cur.fetchone()
print "Query Returned %d row(s)" % cur.rowcount
print row
except sybpydb.Error:
print cur.connection.errors()
finally:
cur.close()
conn.close()
These three calls to the database results in this.
Execute for table1
[DatabaseError("Server message: number(5701) severity(10) state(2) line(0)\n\tChanged database context to 'master'.\n\n", 5701)]
Query Returned -1 row(s)
(Resultset for query 1)
Execute for table2
[DatabaseError("Server message: number(5701) severity(10) state(2) line(0)\n\tChanged database context to 'master'.\n\n", 5701)]
Query Returned -1 row(s)
(Resultset for query2)
[DatabaseError("Server message: number(5701) severity(10) state(2) line(0)\n\tChanged database context to 'master'.\n\n", 5701)]
I never get such message when using sybpydb , I don't print cur.connection.errors() , which is not one of the documented methods (I even got an error when I tried to use it )
In all cases ,maybe you are getting this message as part of Sybase ASE informing the client about:
1- Default database when you log in - I don't think this applied to python .
2- when you change the database context .. which you are doing by specifying "database.."
To get rid of this message , simply set a default database for the user you use to connect as the target database , hence , you connection will be located immediately in that database after login and you don't need to specify the database in the query anymore , to change default database for login use :
sp_modifylogin <uname>, defdb, "<database>"
or in ASE 15.7 :
alter login <uname> modify default database <database>
then your queries should look like :
sql = 'select * from table3 where column1 = ? and column2 ?'

Return a mapped dictionary based on multiple queries

Issue: I can't figure out how to run a query in the correct way so that it returns a mapped dictionary. The query will use counts from multiple tables.
I am using psycopg2 for a postgresql database, and I will be using the results to create a report on day to day deltas on these counts.
Given that, can someone provide an example on how to execute multiple queries and return a dictionary that I can use for comparison purposes? Thanks! I image in a for loop is needed somewhere in here.
tables = ['table1', 'table2']
def db_query():
query = "select count(*) from (a_table) where error_string != '';"
conn = psycopg2.connect(database=db, user=user, password=password, host=host)
cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute(query, tables)
output = cur.fetchall()
conn.close()
return output
I haven't used postgresql, so you might want to also check this out as a reference: How to store count values in python.
That being said, rearrange your code into something like this. Be sure to make conn global so you don't have to make more than one connection, and make sure you're also closing cur:
conn = None
def driverFunc():
global conn
try:
conn = psycopg2.connect(database=db, user=user, password=password, host=host)
tables = ['table1', 'table2']
countDict = {}
for thisTable in tables:
db_query(thisTable, countDict)
finally:
if not conn == None:
conn.close()
def db_query(tableName, countDict):
# Beware of SQL injection with the following line:
query = "select count(*) from " + tableName + " where error_string != '';"
cur = None
try:
cur = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
cur.execute(query)
countDict[tableName] = int(cur.fetchone())
finally:
if not cur == None:
cur.close()

Categories