pyodbc编程错误:('42000',"[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]附近语法不正确。")

8
我正在使用 Python 3.9 通过 Pyodbc 将多个 Google RSS 新闻列表插入到带参数的 SQL 表中,但总是遇到以下程序错误:

cursor.execute(query) pyodbc.ProgrammingError: ('42000', "[42000] [Microsoft][ODBC SQL Server Driver][SQL Server]Incorrect syntax near 'cò' . (102) (SQLExecDirectW)")

我检查了 SQL 表,发现实际上有一些记录已经成功导入到 SQL 中(15 条记录),但并非全部(30 条记录)。
以下是所有代码,请帮忙!
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()

附言:我尝试将文件提取为txt格式,结果完全没问题。


4
要是有人在某个字段中输入'); DROP TABLE Users; --,猜猜会发生什么。不要通过连接用户数据来创建查询语句。无论如何引用或净化都不能保护你免于SQL注入攻击。使用参数化查询更加安全且更容易。 - Panagiotis Kanavos
它起作用了。你救了我的一天。非常感谢! - Ng Hà
2个回答

6

在 Python3 中,在连接(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')

使用psql odbc驱动程序对我有效。 - William Ardila

6

正如@PanagiotisKanavos所评论的,使用行业推荐的SQL参数化最佳实践,不仅适用于Python和SQL Server,而且适用于任何应用程序层代码和任何符合SQL标准的数据库。

这种方法不仅可以安全地转义用户提交的值,还可以避免特殊字符(如您的情况下的重音符号)和字符串中的引号破坏。此外,您可以提高代码的可读性、可维护性和效率。甚至可以考虑使用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()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接