这里的首要问题是如何使用格式" REPLACE INTO ... VALUES(...),(...)格式获得与None一起使用的多行REPLACE INTO语句。
从https://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-executemany.html我们有这个例子,其中INSERT语句的executemany(stmt,params)只构成多行格式:
INSERT INTO employees (first_name, hire_date) VALUES ('Jane', '2005-02-12'), ('Joe', '2006-05-23'), ('John', '2010-10-03')
但是对于所有其他语句类型,它在params中为每个元组创建一个查询。出于性能原因,我们希望以这种多行格式捆绑REPLACE INTO。
字段列表如下所示:
child_item_count,name,type_default,parent_id,version,agent_id,folder_id
,其中一些被允许为NULL。
最初,我尝试构建一个语句字符串,其中包含添加到查询操作部分的所有元组逗号。鉴于list_of_tuples看起来像[(无,'字符串',' UUID',190L,' UUID'' UUID'), ...]:
insert_query = "REPLACE INTO %s ( %s ) VALUES {} " % (table, column_names)
values = ', '.join(map(str, list_of_tuples))
sql = insert_query.format(values)
db_cursor.execute(sql)
但我得到了:
写入数据库时出错:操作错误(1054,"未知列'无'在'字段列表'")
我还尝试将列表运送到execute(),就像在db_cursor.execute(insert_query,list_of_tuples)中那样,并且也不起作用。这会导致" TypeError('并非在字符串格式化期间转换所有参数',)"
答案 0 :(得分:0)
警告:您的代码包含SQL注入的可能性。
问题很简单:
map(a, b)
函数将为b中的每个元素运行a(el)
。
在您的情况下,它将获取列表中的每个元组并将其转换为字符串,因此给定的元组(None, 4, 'b')
将变为(None, 4, 'b')
- 并且None
无效MySQL上的关键字。
解决此问题的最佳方法是依靠execute命令正确转换值,使其 sql injection free :
import itertools
columns_count = 10 # Change this value according to your columns count
column_values = '(' + ', '.join(['%s'] * columns_count) + ')'
values = ', '.join([column_values]*len(list_of_tuples))
# (...)
insert_query = insert_query.format(values)
db_cursor.execute(insert_query, list(itertools.chain.from_iterable(list_of_tuples)))
虽然有第二个选项(Bellow),但它会使您的代码容易受到SQL注入攻击。所以不要使用它。
只需直接转换值,进行必要的调整(在此特定场景中,它只是将None更改为NULL):
values = ', '.join('('+', '.join(map(lambda e: str(e) if e else "NULL", t))+')' for t in list_of_tuples)