As described here https://peps.python.org/pep-0249/#paramstyle, in MySql it should be possible to bind parameters using the keyword syntax, like this: email=:email. This is different from using an unnamed placehoder syntax, like email=%s.
But this code doesn't work:
import pymysql
con = pymysql.connect(host='localhost', user='root', password=pw, database=db_name, port=4306)
stmt = "INSERT INTO `test_table` (`email`, `password`) VALUES (:email, :password)"
with con.cursor() as cursor:
# Create a new record
cursor.execute(stmt, {'email': "FOO", 'password': "BAR"})
con.commit()
Not even adding
pymysql.paramstyle = 'named'
at the top.
The error is
(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 ':email, password=:password)' at line 1")
but unfortunately, I'm not able to find such documentation (This page doesn't document anything.. https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html)
What is the right syntax?
Thanks!
https://pymysql.readthedocs.io/en/latest/modules/cursors.html says:
If args is a list or tuple, %s can be used as a placeholder in the query. If args is a dict, %(name)s can be used as a placeholder in the query.
Even though the :name placeholder format is in the PEP you reference, the pymysql package does not seem to implement that format.
This should work:
stmt = "INSERT INTO `test_table` (`email`, `password`) VALUES (%(email)s, %(password)s)"
with con.cursor() as cursor:
# Create a new record
cursor.execute(stmt, {'email': "FOO", 'password': "BAR"})
Related
I have a following query:
cursor = connection.cursor()
query = """
SELECT *
FROM `my_database`.table_a
"""
result = cursor.execute(query)
which works as expected. But I need to change my_database in cursor.execute. I try:
cursor = connection.cursor()
query = """
SELECT *
FROM %s.table_a
"""
result = cursor.execute(query, ("my_database",))
which gives an error pymysql.err.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 ''my_database'.table_a at line 2")
how can I insert database name in cursor.execute please?
It is not possible to bind a database name (or any other database object name) using a placeholder in a prepared statement. This would be, among other problems, a security risk. However, you might be able to use an f-string here instead:
cursor = connection.cursor()
db_name = "my_database"
query = f"""
SELECT *
FROM {db_name}.table_a
"""
result = cursor.execute(query)
It should also be mentioned that the above is only SQL injection safe if you are certain that the database name is not coming from outside your own application.
I want to use prepared statements to remove a row from a table, but it results in an error: mysql.connector.errors.ProgrammingError: Not all parameters were used in the SQL statement
Relevant code:
db = mysql.connector.connect(
host='localhost',
user='user',
database='web_board',
password='password',
auth_plugin='mysql_native_password'
)
crs = db.cursor()
# construct the query and remove post from the database
query = 'DELETE FROM posts WHERE postid=%s'
crs.execute(query, tuple(request.data))
db.commit()
crs.close()
db.close()
request.data looks like this: b'9b23f24e-ff4d-4113-85ae-ff8a4a5de3be'
As the documentation states, to use prepared statements, you should instantiate your cursor with following config:
crs = db.cursor(prepared=True)
Prepared statements executed with MySQLCursorPrepared can use the format (%s) or qmark (?) parameterization style.
I'm trying to create a database with the name a user will provide. As far as I know the correct way is to use the second argument of execute().
So I did as follows:
import psycopg2
conn = psycopg2.connect(host="...", dbname="...",
user="...", password="...", port='...')
cursor = conn.cursor()
query = ''' CREATE DATABASE %s ;'''
name = 'stackoverflow_example_db'
conn.autocommit = True
cursor.execute(query, (name,))
cursor.close()
conn.close()
And I got this error:
psycopg2.errors.SyntaxError: syntax error at or near "'stackoverflow_example_db'"
LINE 1: CREATE DATABASE 'stackoverflow_example_db' ;
I need to do this statement avoiding SQL injection, so using the second argument is a must.
You can't pass values as second argument of execute(), if the statement is a CREATE DATABASE one.
As pointed out by unutbu one way to approach this is using the psycopg2.sql submodule and use identifiers to build the statement avoiding SQL injection.
The code:
import psycopg2
from psycopg2 import sql
conn = psycopg2.connect(host="...", dbname="...",
user="...", password="...", port='...')
cursor = conn.cursor()
query = ''' CREATE DATABASE {} ;'''
name = 'stackoverflow_example_db'
conn.autocommit = True
cursor.execute(sql.SQL(query).format(
sql.Identifier(name)))
cursor.close()
conn.close()
Other aditional observations:
format() do not work with %s, use {} instead
Autocommit mode is a must for this statement to work
The specified connection user needs creation privileges
I'm inserting data using execute_values, which takes a sql query. The query is constructed using psycopg2.sql.SQL as recommended in the documentation, but execute_values won't take that object.
Here's the code I have:
import psycopg2 as pg
from psycopg2 import extras
from psycopg2 import sql
config = {
'host' : 'localhost',
'user' : 'username',
'password' : 'password',
'dbname' : 'myDatabase'
}
connection = pg.connect(**config)
cursor = connection.cursor()
tableName = 'myTable'
dataset = [[1,2],[3,4],[5,6]]
queryText = "INSERT INTO {table} (uid,value) VALUES %s"
query = sql.SQL(queryText).format(table=sql.Identifier(tableName))
extras.execute_values(cursor,query,dataset)
The last line gives the following error:
AttributeError: 'Composed' object has no attribute 'encode'
If the query is specified directly as a string, as below, then the execution runs.
query = """INSERT INTO "myTable" (uid,value) VALUES %s"""
It's possible to insert the table name into the query using string format, but apparently that shouldn't be done, even at gunpoint. How can I safely insert a variable table name into the query and use execute_values? I can't find a built-in way to convert the SQL object to a string.
The parameter sql in execute_values(cur, sql, argslist, template=None, page_size=100) is supposed to be a string:
sql – the query to execute. It must contain a single %s placeholder, which will be replaced by a VALUES list. Example: "INSERT INTO mytable (id, f1, f2) VALUES %s".
Use the as_string(context) method:
extras.execute_values(cursor, query.as_string(cursor), dataset)
connection.commit()
As execute_values() expect the sql statement to be a string you can simply user:
queryText = "INSERT INTO {table} (uid,value) VALUES %s".format(table=sql.Identifier(tableName)
Here is my code:
from urllib.request import urlopen
from bs4 import BeautifulSoup as bs
import re
import pymysql
resp = urlopen("https://en.wikipedia.org/wiki/Main_Page").read().decode("utf-8")
soup = bs(resp ,"html.parser")
listUrls = soup.findAll("a", href=re.compile("^/wiki/"))
for url in listUrls:
if not re.search('\.(jpg|JPG)$', url['href']):
conn = pymysql.connect(
host='127.0.0.1',
user='root',
password='',
db='wikiurl',
charset='utf8mb4'
)
try:
with conn.cursor() as cursor:
sql = "insert into 'wikiurl'('urlname','urlhref') VALUES (%s , %s)"
cursor.execute(sql,(url.get_text(), "https://en.wikipedia.org" + url["href"]))
conn.commit()
finally:
conn.close()
Error:
pymysql.err.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 ''wikiurl'('urlname','urlhref') VALUES ('Wikipedia' , 'https://en.wikipedia.org/w' at line 1")
First of all, I recommend giving whitespace the utmost attention to detail.
Try this:
sql = "INSERT INTO wikiurl (urlname, urlhref) VALUES (%s, %s)"
Also notice that single quotation marks are not necessary around the table name. See: MySQL Insert documentation.
Edit: And you don't need quotation marks around the column names.
I think your sql syntax has some error,but it is not easy to debug it.
I recommend you use this method to print what the real sql string that is sent to mysql server.pymysql manual above:
mogrify(self, query, args=None)
'''Returns the exact string that is sent to the database by calling the
execute() method.
This method follows the extension to the DB API 2.0 followed by Psycopg.'''
eg:
you can use
print cursor.mogrify(sql,(url.get_text(), "https://en.wikipedia.org" + url["href"]))
good luck!