在一个字符串中执行超过1000个插入语句
我以为这个问题会很简单,但不知道为什么,脚本执行完后数据没有出现在表里。我生成了一个包含超过1000个查询的字符串,目前是1131个,它们用“;”分隔。
这个字符串是通过一个简单的循环创建的:
query = ""
for: #loop condition
query += "INSERT INTO Results (col1, col2, col3, col4, pass) VALUES ('%s', %s, %s, %s, 0);" % (val1, val2, val3, val4)
logger.debug("SQL Query = %s" % query)
try:
cursor.execute(query, multi=True)
except MySQLdb.Error, e:
try:
logger.error("MySQL Error [%d]: %s" % (e.args[0], e.args[1]))
dbinit.cnx.rollback()
cursor.close()
dbinit.cnx.close()
except IndexError:
logger.error("MySQL Error: %s" % str(e))
dbinit.cnx.rollback()
cursor.close()
dbinit.cnx.close()
dbinit.cnx.commit()
cursor.close()
dbinit.cnx.close()
我没有收到任何错误提示,当我打印这个字符串时,它显示得很好。我甚至可以复制粘贴打印出来的内容,然后一次性运行这些SQL命令,它们也能正常执行,所以我没有错误的查询。任何帮助都很感激,因为我现在很困惑。我知道还有其他方法可以做到这一点,但如果有人能解释一下为什么这个方法不行,我也会很感激,这样我可以学习到更多!
更新:Mike的回答在大部分情况下是正确的,但我想更新一下这篇帖子,告诉大家我的代码最后变成了什么样。
queryData=[]
for: #condition
queryData.append((val1, val2, val3, val4, 0))
while len(queryData) != 0:
cursor.executemany("INSERT INTO Results (col1, col2, col3, col4, pass) VALUES (%s, %s, %s, %s, %s)", queryData[:999])
del queryData[:999]
dbinit.cnx.commit()
1 个回答
看起来你可能走了弯路。cursor.execute()
这个方法是用来执行一条查询的,它会准备好这条查询,并用你提供的数据来执行。在这一行
cursor.execute(query, multi=True)
你漏掉了第二个 params
参数,所以没有数据可以执行。
你似乎是把1000多个查询拼成了一条长字符串。你可以尝试用 cursor.query()
来做这个,但如果这样做的话,服务器会重复解析和准备基本相同的查询1000多次,这样效率就低了。无论如何,很多MySQL的类都不允许这样拼接多个查询。
你需要的是 cursor.executemany(query, data)
,这个方法可以构建一条查询,并且可以处理多个值集,每个值集对应你data
中的一行。
我不是Python开发者,也不知道你是从哪里获取数据的,但这是来自 MySQL参考文档 的一个例子,稍微改了一下:
data = [
('col1-1', 1,2,3),
('col1-2', 4,5,6),
('col1-3', 7,8,9),
]
stmt = "INSERT INTO Results (col1, col2, col3, col4, pass) VALUES ('%s', %s, %s, %s, 0)"
cursor.executemany(stmt, data)
你可以添加自己的异常处理。希望这能帮助你入门。
注意:通过这种方式插入的值集数量没有限制,但你创建的字符串长度是有限制的,默认是1Mb。如果你的需求超过了这个限制,你可以把插入分批进行,比如每次500个,然后执行几条查询(3条查询总比1500条要好!),或者看看 cursor.MySQLCursorPrepared
类,它只解析一次查询,然后对你发送的每组数据执行。