I am accessing a MySQL database (V5.5) via a Python program for generating bespoke reports. The standard fields (int, varchar, datetime, etc.) present no problem - in general I am putting these into Python lists for subsequent processing. However one table makes extensive use of BLObs; these hold either Binary/HTML/PDF/PNG/CSV data. My problem is how to handle them once they are returned in a SELECT statement. The Binary data needs further processing and the PNG may need to be inserted into a report.
Thanks in advance...
I have tried various things including code based on:- How to insert / retrieve a file stored as a BLOB in a MySQL db using python
Te relevant snippets are:-
TheData = open("/home/mjh/Documents/DemoData/sjp.bin", 'rb').read()
sql = "Insert into Results (idResults, idClient, TestDateTime, ResultBinary) \
Values (10, 7, '2014-11-05 14:09:11', %s"
cursor.execute(sql, (TheData,))
This comes back with:-
_mysql_exceptions.ProgrammingError: (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 '' at line 1")
Related
I'm trying to implement the code on this video to my mysql database. When I enter the values by hand to python code it works. However when i use python dictionaries for getting entries from gui like the video it's says: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ':b_name, :b_category, :b_status, :b_author)' at line 1
On video he uses SQLite this can be the problem but i'm not sure.
my code is here
# Insert Into Table
c.execute("INSERT INTO `books` (`bookName`, `bookCategory`, `BookCurrentStatus`, `bookAuthor`) VALUES (:b_name, :b_category, :b_status, :b_author)",
{
'b_name': b_name.get(),
'b_category': b_category.get(),
'b_status': b_status.get(),
'b_author': b_author.get()
})
MySQLdb only supports the format and pyformat parameter styles. The named parameter style used in the video isn't supported.
I believe that you are not actually doing string replacement with your current setup, try this:
# Insert Into Table
c.execute("INSERT INTO `books` (`bookName`, `bookCategory`, `BookCurrentStatus`, `bookAuthor`) VALUES ({b_name}, {b_category}, {b_status}, {b_author})",
{
'b_name': b_name.get(),
'b_category': b_category.get(),
'b_status': b_status.get(),
'b_author': b_author.get()
})
Python mysql default escape function, corrupts the query.
Original Query string is following. It works fine and does add records to database as desired
INSERT IGNORE INTO state (`name`, `search_query`, `business_status`, `business_type`, `name_type`, `link`) VALUES ("test_name1", "test", "test_status", "test_b_typ", "test_n_typ", "test_link"), ("test_name2", "test", "test_status", "test_b_typ", "test_n_typ", "test_link")
But After escaping it to make sql Injection secure using the fuction
safe_sql = self.conn.escape_string(original_sql)
safe_sql being generated is following
b'INSERT IGNORE INTO state (`name`, `search_query`, `business_status`, `business_type`, `name_type`, `link`) VALUES (\\"test_name1\\", \\"test\\", \\"test_status\\", \\"test_b_typ\\", \\"test_n_typ\\", \\"test_link\\"), (\\"test_name2\\", \\"test\\", \\"test_status\\", \\"test_b_typ\\", \\"test_n_typ\\", \\"test_link\\")'
Now if I try to execute the safe_sql I get the syntax error below
MySQLdb._exceptions.ProgrammingError: (1064, 'You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near \'\\"test_name1\\", \\"test\\", \\"test_status\\", \\"test_b_typ\\", \\"test_n_typ\\", \\"tes\' at line 1')
Which makes me wonder that if escape function I am using is either broken / uncompatibl or I am not using it the right way ? Also i am entering hundreds of records at one time, and due to the fast processing (which i purely assume) of single query as compared to prepared statements running hundreds of time, I am creating a large query.
You can't escape the entire query! You can't construct a query by randomly concatenating strings and then wave a magic wand over it and make it "injection secure". You need to escape every individual value before you put it into the query. E.g.:
"INSERT ... VALUES ('%s', ...)" % self.conn.escape_string(foo)
But really, your MySQL API probably offers prepared statements, which are much easier to use and less error prone. Something like:
self.conn.execute('INSERT ... VALUES (%s, %s, %s, ...)',
(foo, bar, baz))
My objective is to store a JSON object into a MySQL database field of type json, using the mysql.connector library.
import mysql.connector
import json
jsonData = json.dumps(origin_of_jsonData)
cnx = mysql.connector.connect(**config_defined_elsewhere)
cursor = cnx.cursor()
cursor.execute('CREATE DATABASE dataBase')
cnx.database = 'dataBase'
cursor = cnx.cursor()
cursor.execute('CREATE TABLE table (id_field INT NOT NULL, json_data_field JSON NOT NULL, PRIMARY KEY (id_field))')
Now, the code below WORKS just fine, the focus of my question is the use of '%s':
insert_statement = "INSERT INTO table (id_field, json_data_field) VALUES (%s, %s)"
values_to_insert = (1, jsonData)
cursor.execute(insert_statement, values_to_insert)
My problem with that: I am very strictly adhering to the use of '...{}'.format(aValue) (or f'...{aValue}') when combining variable aValue(s) into a string, thus avoiding the use of %s (whatever my reasons for that, let's not debate them here - but it is how I would like to keep it wherever possible, hence my question).
In any case, I am simply unable, whichever way I try, to create something that stores the jsonData into the mySql dataBase using something that resembles the above structure and uses '...{}'.format() (in whatever shape or form) instead of %s. For example, I have (among many iterations) tried
insert_statement = "INSERT INTO table (id_field, json_data_field) VALUES ({}, {})".format(1, jsonData)
cursor.execute(insert_statement)
but no matter how I turn and twist it, I keep getting the following error:
ProgrammingError: 1064 (42000): 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 '[some_content_from_jsonData})]' at line 1
Now my question(s):
1) Is there a way to avoid the use of %s here that I am missing?
2) If not, why? What is it that makes this impossible? Is it the cursor.execute() function, or is it the fact that it is a JSON object, or is it something completely different? Shouldn't {}.format() be able to do everything that %s could do, and more?
First of all: NEVER DIRECTLY INSERT YOUR DATA INTO YOUR QUERY STRING!
Using %s in a MySQL query string is not the same as using it in a python string.
In python, you just format the string and 'hello %s!' % 'world' becomes 'hello world!'. In SQL, the %s signals parameter insertion. This sends your query and data to the server separately. You are also not bound to this syntax. The python DB-API specification specifies more styles for this: DB-API parameter styles (PEP 249). This has several advantages over inserting your data directly into the query string:
Prevents SQL injection
Say you have a query to authenticate users by password. You would do that with the following query (of course you would normally salt and hash the password, but that is not the topic of this question):
SELECT 1 FROM users WHERE username='foo' AND password='bar'
The naive way to construct this query would be:
"SELECT 1 FROM users WHERE username='{}' AND password='{}'".format(username, password)
However, what would happen if someone inputs ' OR 1=1 as password. The formatted query would then become
SELECT 1 FROM users WHERE username='foo' AND password='' OR 1=1
which will allways return 1. When using parameter insertion:
execute('SELECT 1 FROM users WHERE username=%s AND password=%s', username, password)
this will never happen, as the query will be interpreted by the server separately.
Performance
If you run the same query many times with different data, the performance difference between using a formatted query and parameter insertion can be significant. With parameter insertion, the server only has to compile the query once (as it is the same every time) and execute it with different data, but with string formatting, it will have to compile it over and over again.
In addition to what was said above, I would like to add some details that I did not immediately understand, and that other (newbies like me ;)) may also find helpful:
1) "parameter insertion" is meant for only for values, it will not work for table names, column names, etc. - for those, the Python string substitution works fine in the sql syntax defintion
2) the cursor.execute function requires a tuple to work (as specified here, albeit not immediately clear, at least to me: https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html)
EXAMPLE for both in one function:
def checkIfRecordExists(column, table, condition_name, condition_value):
...
sqlSyntax = 'SELECT {} FROM {} WHERE {} = %s'.format(column, table, condition_name)
cursor.execute(sqlSyntax, (condition_value,))
Note both the use of .format in the initial sql syntax definition and the use of (condition_value,) in the execute function.
I have to delete some dates from mysql by python.
I have tables over 2000. so, I need to finish this code... I can't handle this much by clicking my mouse. I really need help.
well, my guess was like this
sql ="delete from finance.%s where date='2000-01-10'"
def Del():
for i in range(0,len(data_s)):
curs.execute(sql,(data_s[i]))
conn.commit()
Howerver, it doesn't work.
I just though
when I just type like this , it works.
>>> query="delete from a000020 where date ='2000-01-25'"
>>> curs.execute(query) //curs=conn.cursor()
But if I add %s to the syntax, it doesn't work..
>>> table='a000050'
>>> query="delete from %s where date ='2000-01-25'"
>>> curs.execute(query,table)
ProgrammingError: (1064, u"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 ''a000050' where date ='2000-01-25'' at line 1")
it doesn't work too.
>>> curs.execute(query,(table))
ProgrammingError: (1064, u"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 ''a000050' where date ='2000-01-25'' at line 1")
a bit different... but same.
>>> curs.execute(query,(table,))
I have read many questions from here, but by just adding () or , it doesn't fixed...
Because I'm beginner for the python and mysql, I really need your help. Thank you for reading.
I had the same issue and I fixed by appending as:
def Del():
for i in range(0,len(data_s)):
x = "delete from finance." + data_s[i] + "where date='2000-01-10'"
print x # to check the sql statement :)
curs.execute(x)
conn.commit()
Good question,have a look at MySQLdb User's Guide
paramstyle
String constant stating the type of parameter marker formatting
expected by the interface. Set to 'format' = ANSI C printf format
codes, e.g. '...WHERE name=%s'. If a mapping object is used for
conn.execute(), then the interface actually uses 'pyformat' = Python
extended format codes, e.g. '...WHERE name=%(name)s'. However, the API
does not presently allow the specification of more than one style in
paramstyle.
Note that any literal percent signs in the query string passed to execute() must be escaped, i.e. %%.
Parameter placeholders can only be used to insert column values. They
can not be used for other parts of SQL, such as table names,
statements, etc.
Hope this helps.
I have a huge data which is stored in mysql db. One of the columns in the database is a long string. One of the strings is "iEdge detected the 'warning' condition 'iedge it" which is stored in string_type. I have to query the database and find how many such strings are there.I am querying from my python program. When I do it using something like
cur.execute("select count(*) from table1 as tmp where tmp.err_string='"+row[r]+"'")
row[r] contains "iEdge detected the 'warning' condition 'iedge it"
I am getting error 1064 (You have an error in your SQL syntax...). I think it is happening because of some quotes in the string. May I know how to fix this?
Can you try this:
sql = "select count(*) from table1 as tmp where tmp.err_string=%s"
cursor.execute(sql, [row[r]])
Let the MySQL Python library worry about escaping special characters and how to quote your string.
See this SO post for more information.