如何使用Python连接器到mySQL来REPLACE INTO多行

时间:2018-03-26 23:47:03

标签: python mysql

这里的首要问题是如何使用格式" 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('并非在字符串格式化期间转换所有参数',)"

1 个答案:

答案 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)