在python MySQLdb的executemany()中包含数据库函数调用

2 投票
1 回答
2378 浏览
提问于 2025-04-16 11:06

当我尝试运行像这样的语句时:

cursor.executemany("""INSERT INTO `test` (`id`,`data`,`time_added`) 
                      VALUES (%s, %s, NOW())""", [(i.id, i.data) for i in items])

MySQLdb 在处理 NOW() 里的右括号时出现问题,因为它把这个括号当成了值块的结束。这意味着,查询看起来像这样:

('1', 'a', NOW(), ('2','b', NOW(), ('3','c',NOW())

而 MYSQL 报告了一个语法错误。实际上,它们应该看起来像这样:

('1', 'a', NOW()), ('2','b', NOW()), ('3','c',NOW())

应该有某种方法可以处理 NOW(),但我不知道怎么做。把 'NOW()' 加入到元组里不行,因为这样 NOW() 就被引起来了,数据库把它当成字符串,而不是函数调用。

通过使用当前时间戳作为默认值来解决这个问题也不行——这只是一个例子,我需要用各种数据库函数来做这种事情,而不仅仅是 NOW()。

谢谢!

1 个回答

1

下面这个方法并不是最理想的,但不幸的是,这是我知道的唯一方法。

这个想法是手动构建SQL语句,使用 connection.literal 来帮你处理参数的转义:

cursor=connection.cursor()
args=[(1,'foo'),(2,'bar')]
sql=('INSERT INTO `foo` (`fooid`,`data`,`time_added`) VALUES '
     +','.join(
         ['(%s,%s,NOW())'%connection.literal(arg)
          for arg in args]))
cursor.execute(sql)

这看起来很糟糕,可能让你觉得不舒服,但如果你深入了解(在 /usr/lib/pymodules/python2.6/MySQLdb/cursors.py 文件中)MySQLdb 在 cursors.executemany 中做了什么,我觉得这和那个函数的做法差不多,只是因为正则表达式 cursors.insert_values 没有正确解析嵌套的括号而导致了一些混乱。(哎呀!)


我刚刚 安装了 oursql,这是 MySQLdb 的一个替代品,很高兴地报告说

sql='INSERT INTO `foo` (`fooid`,`data`,`time_added`) VALUES (?,?,NOW())'
cursor.executemany(sql,args)

在使用 oursql 时,效果如预期。

撰写回答