我的数据库结构如下所示:
当前值
| file_id | file_path |
+---------+-------------+
| 1 | path\test |
+---------+-------------+
| 2 | path\test2 |
+---------+-------------+
| 2 | path\test3 |
+---------+-------------+
使用sqlalchemy
,我尝试使用func.replace
将反斜杠替换为file_path
列中的正斜杠。
期望值
| file_id | file_path |
+---------+-------------+
| 1 | path/test |
+---------+-------------+
| 2 | path/test2 |
+---------+-------------+
| 3 | path/test3 |
+---------+-------------+
截至目前,我正在单独更新每一行,并且我能够毫无问题地执行替换
from sqlalchemy import Table, MetaData, Column, Integer, String, func, create_engine
table = Table('file_table', MetaData(), Column('id', Integer), Column('file_path', String))
file_ids = [1, 2, 3]
connection = create_engine('connections_string')
cursor = connection.connect()
for file_id in file_ids:
q_ = table.update().values({'file_path': func.replace(table.c.file_path, '\\', '/')}).where(table.c.file_id == file_id)
cursor.execute(query)
cursor.close()
我试图将其转换为批量更新,而不是单独进行每次更新。我以前做过批量更新,以下是我通常会执行一次
的方式scripts = [{'file_path': 'new_column_value', 'bk_file_id': f} for f in [1,2,3]]
q_ = table.update().where(table.c.file_id == bindparam('bk_file_id'))
cursor.execute(q_, scripts)
以上情况正常,但在实施func.replace
scripts = [{'file_path': func.replace(table.c.file_path, '\\', '/'), 'bk_file_id': f} for f in [1,2,3]]
q_ = table.update().where(table.c.file_id == bindparam('bk_file_id'))
cursor.execute(q_, scripts)
回溯
Traceback (most recent call last):
File "bulk_update.py", line 15, in <module>
cursor.execute(q_,scripts)
File "C:\Python35\lib\site-packages\sqlalchemy\engine\base.py", line 914, in execute
return meth(self, multiparams, params)
File "C:\Python35\lib\site-packages\sqlalchemy\sql\elements.py", line 323, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "C:\Python35\lib\site-packages\sqlalchemy\engine\base.py", line 1010, in _execute_clauseelement
compiled_sql, distilled_params
File "C:\Python35\lib\site-packages\sqlalchemy\engine\base.py", line 1146, in _execute_context
context)
File "C:\Python35\lib\site-packages\sqlalchemy\engine\base.py", line 1344, in _handle_dbapi_exception
util.reraise(*exc_info)
File "C:\Python35\lib\site-packages\sqlalchemy\util\compat.py", line 186, in reraise
raise value
File "C:\Python35\lib\site-packages\sqlalchemy\engine\base.py", line 1116, in _execute_context
context)
File "C:\Python35\lib\site-packages\sqlalchemy\dialects\mysql\mysqldb.py", line 95, in do_executemany
rowcount = cursor.executemany(statement, parameters)
File "C:\Python35\lib\site-packages\pymysql\cursors.py", line 195, in executemany
self.rowcount = sum(self.execute(query, arg) for arg in args)
File "C:\Python35\lib\site-packages\pymysql\cursors.py", line 195, in <genexpr>
self.rowcount = sum(self.execute(query, arg) for arg in args)
File "C:\Python35\lib\site-packages\pymysql\cursors.py", line 164, in execute
query = self.mogrify(query, args)
File "C:\Python35\lib\site-packages\pymysql\cursors.py", line 143, in mogrify
query = query % self._escape_args(args, conn)
File "C:\Python35\lib\site-packages\pymysql\cursors.py", line 123, in _escape_args
return dict((key, conn.literal(val)) for (key, val) in args.items())
File "C:\Python35\lib\site-packages\pymysql\cursors.py", line 123, in <genexpr>
return dict((key, conn.literal(val)) for (key, val) in args.items())
File "C:\Python35\lib\site-packages\pymysql\connections.py", line 800, in literal
return self.escape(obj, self.encoders)
File "C:\Python35\lib\site-packages\pymysql\connections.py", line 793, in escape
return escape_item(obj, self.charset, mapping=mapping)
File "C:\Python35\lib\site-packages\pymysql\converters.py", line 27, in escape_item
val = encoder(val, mapping)
File "C:\Python35\lib\site-packages\pymysql\converters.py", line 110, in escape_unicode
return u"'%s'" % _escape_unicode(value)
File "C:\Python35\lib\site-packages\pymysql\converters.py", line 73, in _escape_unicode
return value.translate(_escape_table)
File "C:\Python35\lib\site-packages\sqlalchemy\sql\elements.py", line 738, in __getattr__
key)
AttributeError: Neither 'Function' object nor 'Comparator' object has an attribute 'translate'
如何使用func
来解决此错误以执行批量更新?
答案 0 :(得分:1)
您的问题来自于executemany
values
形式的executemany
不支持表达式,但对于批量更新,您不应该使用UPDATE file_table SET file_path = replace(file_path, '\\', '/') WHERE file_id = 1;
UPDATE file_table SET file_path = replace(file_path, '\\', '/') WHERE file_id = 2;
UPDATE file_table SET file_path = replace(file_path, '\\', '/') WHERE file_id = 3;
表单。
基本上你以前做的是:
UPDATE file_table SET file_path = replace(file_path, '\\', '/') WHERE file_id IN (1, 2, 3);
您正试图通过批量更新模仿确切的查询。为什么不改为运行单个查询呢?
table.update().values({'file_path': func.replace(table.c.file_path, '\\', '/')}).where(table.c.file_id.in_(file_ids))
在SQLAlchemy中这样做的方式与您之前完成的工作完全相同:
UserData