Python MySQL executemany的使用

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python MySQL executemany的使用相关的知识,希望对你有一定的参考价值。

有数据库test,其中有表test,包含两个字段‘name’,‘age’,分别为varchar跟int型。

以下为语句片段:
values = [('person_a',28),('person_b',29)]
cur.executemany("insert into test(name,age) values (%s,%d)", values)

报错:
mysql Error 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 '%s,%d),
(%s,%d)' at line 2

求大侠指教。

个人理解:

execute中要使用对等格式 如 name(char), age(int),此时语句为: cur.execute("insert into db.table(name,age) values(%s,%d)" % (v[name], v[age]) ,v[name]为字符,v[age]为int

executemany中不需要强制格式,同上表语句为:
values=[("zhan",23),("li",33)]
executemany("insert into db.tables(name,age) values(%s,%s)",values)

具体原因我也不清楚,只能说是走过的坑吧,executemany一般只用%s即可,用其它的可能会报错。插入后的值是正常的(貌似是自动匹配列属性?),有大侠知道的也望指教
参考技术A

这TM是神坑。

python2.x 用的是

"%s %s " % (a, b)

没错


而 python3.x 用的是

"0 1".format(a, b)

而 executemany 对 0 之类的参数格式化支持不完全,格式化出来的 sql 语句对于字符串值不加引号(比如格式化出来的 sql 语句是 'insert into mytable values(中文, string here))',还要手动给 sql 加引号,而加了引号的参数还神TM认不出,抛出错误 Incorrect number of bindings supplied. The current statement uses 0, and there are 3 supplied. 简直日了狗。

只能逐条 sql 语句手动格式化后,再用 execute 执行。


ps. 我说的是 sqlite,其它数据库情况可能不同。

参考技术B SQL语句写的不对,cur.executemany("insert into test(name,age) values ('"+values[person_a]+"','"+values[person_b]+"')") 参考技术C 把%s 改为 '%s'追问

写成cur.executemany("insert into test(name,age) values ('%s',%d)", values)吗?
还是报错。

另外%d的用法对吗?

谢谢

参考技术D 改成%s,%s试一下。

mycursor.executemany 更新未按预期工作

【中文标题】mycursor.executemany 更新未按预期工作【英文标题】:mycursor.executemany UPDATE not working as expected 【发布时间】:2019-05-28 07:07:14 【问题描述】:

问题:

我有一个 python 脚本来抓取和网站,它获取 2 个变量并将它们存储在 2 个列表中。然后,我使用 executemany 更新 MySQL 数据库,使用一个变量匹配预先存在的行以将另一个变量插入其中。

代码:

Python 脚本

import mysql.connector
from bs4 import BeautifulSoup as soup
from selenium import webdriver
import time, re

mydb = mysql.connector.connect(
  host="host",
  user="user",
  passwd="passwd",
  database="database"
)

mycursor = mydb.cursor()

d = webdriver.Chrome('D:/Uskompuf/Downloads/chromedriver')
d.get('https://au.pcpartpicker.com/products/cpu/overall-list/#page=1')
def cpus(_source):
  result = soup(_source, 'html.parser').find('ul', 'id':'category_content').find_all('li')
  _titles = list(filter(None, [(lambda x:'' if x is None else x.text)(i.find('div', 'class':'title')) for i in result]))
  data = [list(filter(None, [re.findall('(?<=\().*?(?=\))', c.text) for c in i.find_all('div')])) for i in result]
  return _titles, [a for *_, [a] in filter(None, data)]


_titles, _cpus = cpus(d.page_source)
sql = "UPDATE cpu set family = %s where name = %s"
mycursor.executemany(sql, list(zip(_cpus, _titles)))
print(sql, list(zip(_titles, _cpus)))
_last_page = soup(d.page_source, 'html.parser').find_all('a', 'href':re.compile('#page\=\d+'))[-1].text
for i in range(2, int(_last_page)+1):
   d.get(f'https://au.pcpartpicker.com/products/cpu/overall-list/#page=i') 
   time.sleep(3)
   _titles, _cpus = cpus(d.page_source)
   sql = "UPDATE cpu set family = %s where name = %s"
   mycursor.executemany(sql, list(zip(_cpus, _titles)))

mydb.commit()

MySQL 更新代码

sql = "UPDATE cpu set family = %s where name = %s"
mycursor.executemany(sql, list(zip(_cpus, _titles)))

MySQL UPDATE 代码打印

print(sql, list(zip(_cpus, _titles)))

MySQL UPDATE 代码打印输出

UPDATE cpu set family = %s where name = %s [('Pinnacle Ridge', 'AMD Ryzen 5 2600'), ('Coffee Lake-S', 'Intel Core i7-8700K'),...

表格的前 2 行

预期结果

第一个变量是名称,即需要匹配的变量,第二个变量是要更新为行的族。名称完全匹配,运行程序时没有错误,但是所有家庭值都是空的。

不确定解决这个问题的最佳方法是什么,虽然我可以做一个小提琴但不确定 executemany 中的列表?

其他

如果您需要更多信息,请告诉我。

谢谢

【问题讨论】:

我可以问一个问题吗?任何名称的值都是Pinnacle Ridge。因为我运行了一个像cur.executemany("UPDATE test SET col = %s WHERE col = %s", [("a","1"),("b","2")]) 这样的小例子,所以效果很好。 对不起,我不确定我是否完全理解名称值是 AMD Ryzen 5 2600、Intel Core i7-8700k 等,该系列是 Pinnacle Ridge、Coffe-Lake-S。我不确定订单是否不正确,如果是,我该如何重新排列? 我认为您应该解决您的问题,您打印的内容和您在 executemany 中使用的内容不同。 其实你的情况让我很困惑。我创建了一个类似的表并首先在_titles 中插入所有值。然后使用你的部分代码(在for循环之前),我得到了你想要的| AMD Ryzen 5 2600 | Pinnacle Ridge | | Intel Core i7-8700K | Coffee Lake-S | | AMD Ryzen 7 2700X | Pinnacle Ridge | | AMD Ryzen 3 2200G | Raven Ridge | 抱歉,我不确定您的意思是什么,我正在尝试通过名称实现与行匹配的家庭?你知道我需要在我的代码中改变什么来实现这一点吗? 【参考方案1】:

只需要补充:

mydb.commit()

之后

executemany

【讨论】:

以上是关于Python MySQL executemany的使用的主要内容,如果未能解决你的问题,请参考以下文章

Python MySQL executemany的使用

如何使用 MySQL executemany 更新 Python 中的列表列表?

MySQL 和 Python:Auto_Increment 不适用于 cursor.executemany()

如何使用 executemany 将 Python 中的字典列表插入 MySQL

Python mysql executemany() and commit vs many execute() and commit

MySQLdb使用批量插入executemany方法插入mysql