use*_*087 5 python mysql sqlalchemy pymysql
我的程序执行 SQL 插入时一直遇到一个奇怪的问题。我定期(每天一次)在单个 INSERT 语句中使用 pymysql 发送大量数据,每隔几天我就会收到以下错误:
(sqlalchemy.exc.InvalidRequestError) A value is required for bind parameter 'D' [SQL:
在我的代码中,这是数据库连接和插入完成的方式:
会话创建:
engine = sqlalchemy.create_engine(db_host, echo = False)
self.metadata = sqlalchemy.MetaData(engine)
DB_session = sqlalchemy.orm.sessionmaker(bind = engine)
session = DB_session()
Run Code Online (Sandbox Code Playgroud)
插入功能:
def insert(self,sql):
complete = False
try:
self.session.execute(sql)
self.session.commit()
complete = True
except Exception as e:
# Do some logging
finally:
return complete
Run Code Online (Sandbox Code Playgroud)
典型的插入语句如下所示:
INSERT INTO my_db.my_table (field_1, field_2, field_3, ... field_32)
VALUES(data_set1),(data_set2),(data_set3)...(data_set500)
ON DUPLICATE KEY UPDATE
field_1=VALUES(field_1), field_2=VALUES(field_2), field_3=VALUES(field_3) ... field_32=VALUES(field_32)
Run Code Online (Sandbox Code Playgroud)
我查过这个问题,通常情况下,当用户显式设置绑定参数并且缺少一个参数时,似乎会发生这种情况,但我不明白为什么我的代码会发生这种情况,而我没有设置任何参数,而且我没有字段说出“D”的名称或知道“D”指的是什么。另外,更令人困惑的是,当我将完全相同的语句插入 MySQL Workbench 时,它执行时没有任何问题。
我认为问题可能源于尝试同时发送太多数据,因为我试图更新/插入大量数据,每个数据都有很多字段。但如果是这样的话,由于我不想将其分成 500 多个单独的插入,那么多少数据才算是过多呢?
您应该使用sqlalchemy 的文本 sql功能来发送纯 sql 查询,但请注意 sqlalchemy 假定您的查询已被清理。
尝试简单地将您的查询转换为文本:
from sqlalchemy.sql import text
session = ...
session.execute(text(sql))
Run Code Online (Sandbox Code Playgroud)
请注意,默认情况下它将使用 autocommit=True,如果您想关闭它,请检查此文档
否则,在 sqlalchemy 中还有另外 2 种方法来处理绑定参数:
如果您已经拥有 sqlalchemy 的Table&Column对象,则首选方法和最面向对象的方法是使用Bind Parameter Objects
或者,您可以使用手动格式化的普通查询并提供带有绑定参数的字典,假设我有一个test包含 2 列id& 的表name。这是最安全的,因为它将依赖 sqlalchemy 来清理参数:
from sqlalchemy.sql import text
session = ...
insert_qry = """
INSERT INTO test (id, name) VALUES(:id1, :name1), (:id2, :name2)
ON DUPLICATE KEY UPDATE id=VALUES(id), name=VALUES(name)
"""
params = {'id1':1, 'name1': 'John', 'id2':2, 'name2': 'Bill'}
session.execute(text(insert_qry), params)
Run Code Online (Sandbox Code Playgroud)