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!
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.
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"})
I'm using python 3.9 to insert a list of multiple news from google rss news to SQL table with parameter using pyobc but always getting programming error below:
cursor.execute(query) pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'cò'
. (102) (SQLExecDirectW)")
I checked the sql table and found out actually some of records had been imported to SQL successfully (15 records ) but not all of its (30 records)
Below its all of my codes pls help !
import bs4
from bs4 import BeautifulSoup as soup
from urllib.request import urlopen
import pyodbc
news_url="https://news.google.com/rss?hl=vi&gl=VN&ceid=VN:vi"
Client=urlopen(news_url)
xml_page=Client.read()
Client.close()
soup_page=soup(xml_page,"xml")
news_list=soup_page.findAll("item")
cnxn = pyodbc.connect('DRIVER={SQL Server};SERVER=ADMIN;DATABASE=NewsCollect2')
cursor = cnxn.cursor()
for news in news_list:
query = f"insert into news2(Title,Source1,Time1) values (N'"+news.title.text+"',N'"+news.source.text+"',N'"+news.pubDate.text+"')"
cursor.execute(query)
cursor.commit()
cursor.close()
cnxn.close()
p/s I tried to extract to txt file and it worked totally fine
As commented by #PanagiotisKanavos, use the industry recommended best practice of SQL parameterization which goes beyond Python and SQL Server but any application layer code and any SQL-compliant database.
Not only does this method safely escape user-submitted values, you also avoid breakage with special characters such as accent marks per your case and even quotes within the strings. Additionally, you enhance code readability, maintainability, and arguably efficiency. Even consider executemany:
# PREPARED STATEMENT (NO DATA)
query = "insert into news2 (Title, Source1, Time1) values (?, ?, ?)"
# LIST OF TUPLES FOR PARAMS
data = [(news.title.text, news.source.text, news.pubDate.text) for news in newslist]
# EXECUTE STATEMENT AND BIND PARAMS
cursor.executemany(query, data)
cursor.commit()
in python3, you need to add two lines after your conn
import pyodbc as db # forgot the imports
conn = pyodbc.connect(driver=driver, server=serv, database=db,port = prt,
uid=usr, pwd=passwd)
conn.setdecoding(db.SQL_CHAR, encoding='latin1')
conn.setencoding('latin1')
I am using Python and a MySQL database and am attempting to itterate through rows in a CSV file and insert them in my database. I have the following:
import mysql.connector
import pandas as pd
mydb = mysql.connector.connect(
host="localhost",
user="root",
passwd="root",
database="mydb")
cursor = mydb.cursor()
cursor.execute("SET FOREIGN_KEY_CHECKS=0")
csv_data = pd.read_csv("file path")
sql = "INSERT INTO table (ID, SecondID, StartDate, EndDate) VALUES (%s, %s, %s, %s)"
for index, row in csv_data.iterrows():
cursor.execute(sql, row)
cursor.execute("SET FOREIGN_KEY_CHECKS=1")
mydb.commit()
cursor.close()
mydb.close()
I can't see what's wrong with the SQL.
Getting the following error:
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 '%s, %s, %s, %s)'
NOTE - The rest of the code seems to work okay and the SQL works fine if I insert specific values but when I try to use the %s construct it fails yet other responses I have seen appear to recommend this as the correct syntax.
Please help- what am I doing wrong?
I think you better use pandas to_sql function.
I'm not sure whether mysql.connector works so i'll use sqlalchemy.
It looks like that:
ENGINE = sqlalchemy.create_engine('mysql+pymysql://root:root#localhost:3306/mydb')
with ENGINE.connect() as connection:
ENGINE.execute("SET FOREIGN_KEY_CHECKS=0")
csv_data.to_sql('table_name', connection, if_exists='append', index=False)
ENGINE.execute("SET FOREIGN_KEY_CHECKS=1")
Look like that the problem is that you are invoking the query without scape the value.
The execute function its getting a class and not an array
for index, row in csv_data.iterrows():
cursor.execute(sql, row)
You should generate an array with all the values and then invoke the query.
Something like:
for index, row in csv_data.iterrows():
params = map(lambda x : x.value, row)
cursor.execute(sql,params)
Be carefull, the size of the array has to be the same size as the values params.
In this case 4
Thank you that was very helpful, I made one minor change and it works perfectly now. Here is the final solution I used:
import pandas as pd
import sqlalchemy
engine = sqlalchemy.create_engine('mysql+pymysql://root:root#localhost:3306/mydb')
csv_data = pd.read_csv("file path")
engine.execute("SET FOREIGN_KEY_CHECKS=0")
with engine.connect() as connection:
csv_data.to_sql('table', connection, if_exists='append', index=False)
engine.execute("SET FOREIGN_KEY_CHECKS=1")
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