This question already has answers here:
Python SQLite how to get SQL string statement being executed
(4 answers)
Closed 2 years ago.
Here I see the suggested way of building queries with python and sqlite3:
t = ('RHAT',)
c.execute('SELECT * FROM stocks WHERE symbol=?', t)
print(c.fetchone())
How do I print the query instead of the result? I know it's not a string, and so a "print sql" statement wouldn't work. In my case, I am running flask and I want to have this code responding to an API invocation:
...
cur = conn.cursor()
arguments = (username, password, )
query = 'SELECT * FROM logins where ((username = ?) AND (password = ?));', arguments
return(query)
...
I would expect to see this query, not to execute it. However, I receive this output:
ValueError: too many values to unpack (expected 2)
Furthermore, I didn't see any method that exports the last query issued in the SQLite.
This might not be the answer you're looking for, but you can format the query as a string using python string format and print, before formatting again using db-api within the c.execute() statement. As long as you only format the executed query with db-api, you're not at risk from sql injection.
Related
This question already has an answer here:
Dynamic SQL Queries with Python and mySQL
(1 answer)
Closed 3 months ago.
I am unable to execute the following statement I keep getting SQL syntax errors.
According to all the examples I can find this should work
Any help will be greatly appreciated.
d2 = df.iloc[-1,:]
q = symbol+'_ivol'
query = """SELECT close FROM %s WHERE date = %s"""
VALUES= (q, d2[1])
cursor.execute(query, VALUES)
ivol = cursor.fetchall()
conn.close()
Query parameters in SQL are not just string substitution. You can't use a query parameter for a table identifier. Parameters can only be used where you would normally use a quoted string literal or numeric literal.
Stated another way, all the identifiers must be fixed in the query string before you prepare it, because identifiers must be validated during the prepare phase, to make sure the table is a valid identifier, and that the table exists. You can't pass the name of a table identifier after the query has been prepared.
The Python driver unfortunately makes this more confusing because it uses %s instead of MySQL's own ? symbol for the parameter placeholder. This makes developers naturally think that %s is simply string substitution, like it is for Python string formatting.
So there's %s and there's %s, and they are handled differently. I know, it's confusing.
So you can do a plain string-formatting substitution to put your table into the query string:
query = """SELECT close FROM %s WHERE date = %%s""".format(q)
But it's more idiomatic for modern Python to use f-string formatting:
query = f"""SELECT close FROM `{q}` WHERE date = %s"""
I put back-ticks around the table name, just in case it's a SQL reserved keyword or something.
Then the other %s is an actual query parameter, because it works as a scalar value in the SQL expression. In this query, there is just one query parameter.
VALUES= [ d2[1] ]
cursor.execute(query, VALUES)
This question already has answers here:
How can prepared statements protect from SQL injection attacks?
(10 answers)
Closed 11 months ago.
What is the best way to sanitize a SQL to prevent injection when using python? I'm using mysql-connector. I have read that I should use a structure similar to:
import mysql.connector
connection = mysql.connector.connect(host="", port="", user="", password="", database="")
cursor = connection.cursor( buffered = True )
sql = "INSERT INTO mytable (column1, column2) VALUES (%s, %s)"
val = (myvalue1, myvalue2)
cursor.execute(sql, val)
connection.commit()
However, I don't understand why this can prevent an injection. Is this sufficient? A user could introduce me anything on myvalue1 or myvalue2, even if it is not suposed to. Is there any useful library?
SQL injection works when untrusted input is interpolated into an SQL query and the input contains characters that change the syntax of the query.
Query parameters are kept separate from the SQL query, never interpolated into it. The values of the parameters are combined with the SQL query after it is parsed, so there is no longer any opportunity to change the syntax. The parameter is guaranteed to be treated as a single scalar value (i.e. as if it's just a string literal in an SQL expression).
This is the way the Python connector works if you use the MySQLCursorPrepared cursor subclass. See https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursorprepared.html
Otherwise, the Python connector "simulates" prepared queries. It actually does interpolate parameters into the SQL query before it is parsed, but it does so safely, by escaping special characters that would cause SQL injection. It is well-tested so it's reliable.
Both cursor types are used the same way, passing an SQL query string with %s placeholders, and another argument with a tuple of parameter values. You are using it correctly.
Re comment from #Learningfrommasters:
Yes, a string stored in your database can be used unsafely in another SQL query, and cause SQL injection. Some people think that only user input must be treated safely, but this is not true. Any variable should be treated as a query parameter, whether the value for that variable comes from user input, or read from a file, or even pulled out of your own database.
Example: Suppose my name is Bill O'Karwin. It has an apostrophe in it, which you know is a special character to SQL because it terminates a string literal.
If my name were stored in the database and then fetched into an application into a variable userlastname, then I could search for other people with the same last name:
sql = f"SELECT * FROM Users WHERE lastname = '{userlastname}'"
That is unsafe because the apostrophe would cause SQL injection. Even though the value didn't come directly from user input, it came from my own database.
So use parameters for all variables. Then you don't have to think about whether the source is safe or not.
sql = "SELECT * FROM Users WHERE lastname = %s"
cur.execute(sql, (userlastname,))
This question already has answers here:
Not all parameters were used in the SQL statement (Python, MySQL)
(5 answers)
Closed last year.
error imageActually I am trying to create flask web application in which, I wanted to store my input values from html webpage into MySQL database, but am getting error as Not all parameters were used in the SQL statement when calling my insert function.
Please find my code
import mysql.connector as conn
def insert_records(name,email,location,salary,band):
con=conn.connect(host='localhost',user='root',password='my password',database="my database")
cur=con.cursor()
sql="""insert into emp1.emp(Name,Email,Location,Salary,Band) values (%s,%s,%s,%d,%s)"""
val=(name,email,location,salary,band)
cur.execute(sql,val)
con.commit()
con.close()
You need to use %s for every argument per the documentation - they use %s for strings, integers, datetimes, etc.
https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-execute.html
This question already has answers here:
Python MySQLdb TypeError: not all arguments converted during string formatting
(8 answers)
Closed 5 years ago.
I'm using Python CGI and MySQL (phpmyadmin). I'm trying to run this SQL statement in python: (tk_journey = 620 for this example - where the %s is)
SELECT tk_id, tk_seat_number FROM tickets
WHERE tk_journey = '%s'
ORDER BY tk_id DESC LIMIT 1;
It works perfectly in phpmyadmin and displays what it should (which is this):
tk_id tk_seat_number
94 2
However, when I run this through a python script it returns None/NoneType for each.
I've tried using this: SELECT MAX(tk_id), tk_seat_number FROM tickets WHERE tk_journey = '%s' but that gave the same result.
I tried to use %s without the quotes but it also generated an error - in mysql syntax. I also tried closing and opening the database connection - didn't work.
I've tried researching this problem a lot but to no help.
Here is the python code:
def getSeatNum(jid):
statement = '''SELECT tk_id, tk_seat_number FROM tickets
WHERE tk_journey = '%s'
ORDER BY tk_id DESC LIMIT 1;'''
cursor.execute(statement, jid)
row = cursor.fetchone()
seat_num = row[0]
return(seat_num)
seat_no = getSeatNum(jid)
jid = 620.
The db connection works fine as there are several other functions similar to this selecting/inserting information into tables, but this one seems to be failing?
Thanks in advance!
EDIT: I'm not sure if this is what I am meant to do. This got marked as a duplicate of this question: Python MySQL TypeError. I never got this TypeError. If the program ran without generating an error - it just returned 'NULL', which in turn affected a later program as the variable would just be 'NULL'. The errors I would get were the SQL syntax error as shown above and various Python errors when I was fiddling around to get it to work. Not this TypeError one.
The second argument to cursor.execute() must be a tuple containing the values to fill in all the placeholders in the query. Even if there's only one placeholder, you need a tuple. So it should be:
cursor.execute(statement, (jid,))
I'm trying to insert a string into a SQLite Select statement in python. When I try this code:
cur.execute("SELECT * FROM DB WHERE employeeNum = '?'",(empNum,))
I get this error:
sqlite3.ProgrammingError: Incorrect number of bindings supplied. The current statement uses 0, and there are 1 supplied.
When I try this code:
cur.execute("SELECT * FROM DB WHERE employeeNum = '",empNum,"'")
I get this error:
TypeError: function takes at most 2 arguments (3 given)
How do I query this string? Sorry I'm new to python. Any help would be greatly appreciated!
Do not use string formatting to insert query parameters into the query - this would make sql injections possible, you would have problems with characters that need to be escaped, with data type conversions etc.
Eliminate the quotes around ? and continue using parameterized query parameters:
cur.execute("SELECT * FROM DB WHERE employeeNum = ?", (empNum, ))
The quotes around ? made sqlite interpret ? as a string, not a placeholder.
Also see similar problem:
SQLite parameter substitution and quotes