SQLAlchemy批量插入时如何正确使用数据库函数?
解决SQLAlchemy批量插入时调用数据库函数的问题
这个问题我之前也踩过坑!原因很简单:单行插入时SQLAlchemy会正确解析你传入的数据库函数表达式,但普通的批量插入(比如直接传字典列表)会把函数字符串当成普通的字面量值,所以才会出现concat(:concat_1, :concat_2)这种奇怪的内容。下面给你两种靠谱的解决方式:
方式1:ORM模式下创建模型实例并赋值函数表达式
如果你用的是SQLAlchemy ORM,不要直接传字典列表,而是创建模型类的实例,把字段直接赋值为用func构造的数据库函数表达式。这样SQLAlchemy会自动识别这是SQL语句的一部分,而不是字符串值。
举个例子:
from sqlalchemy import func from your_module import MyModel, session # 正确姿势:用func构造函数表达式赋值给实例字段 instances = [ MyModel(example_field=func.concat('foo', 'bar')), MyModel(example_field=func.concat('hello', 'world')), # 也可以绑定变量,比如从外部传入参数 MyModel(example_field=func.concat(user_input1, user_input2)) ] # 批量添加并提交 session.add_all(instances) session.commit()
方式2:Core模式下用insert构造器结合bindparam
如果用SQLAlchemy Core(直接操作表对象),可以通过insert()构造器配合bindparam来批量绑定参数,同时指定字段为数据库函数表达式。
示例代码:
from sqlalchemy import insert, func, bindparam from your_module import engine, my_table # 构造insert语句,指定example_field为concat函数,绑定两个参数 stmt = insert(my_table).values( example_field=func.concat(bindparam('part1'), bindparam('part2')) ) # 准备批量数据,对应上面绑定的参数名 batch_data = [ {"part1": "foo", "part2": "bar"}, {"part1": "hello", "part2": "world"}, {"part1": "sql", "part2": "alchemy"} ] # 执行插入 with engine.connect() as conn: conn.execute(stmt, batch_data) conn.commit()
为什么之前的批量插入会失败?
你之前可能用了类似bulk_insert_mappings或者直接给insert().values()传字典列表的方式,这类方法是为了高性能批量插入设计的,它们会把传入的字典值当作纯字面量处理,不会解析其中的SQL表达式。所以你传入的concat(...)字符串会被直接插入到数据库中,而不是被当作函数执行。
内容的提问来源于stack exchange,提问作者Beowulfenator
相关产品推荐
相关产品推荐

