我的表格在一列上具有独特的约束,例如:
CREATE TABLE entity (
id INT NOT NULL AUTO_INCREMENT,
zip_code INT NOT NULL,
entity_url VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY ix_uniq_zip_code_entity_url (zip_code, entity_url)
);
和相应的 SQLAlchemy 模型。我添加了很多记录并且不想在每条记录之后提交 session 。我的假设是多次调用 session.add(new_record)
和一次 session.commit()
。
但是在添加新记录时我可能会得到 IntegrityError
因为约束被违反了。这是正常情况,我只想跳过这样的记录插入。但看起来我只能恢复整个交易。
此外,我不想添加另一个复杂的检查“从数据库中获取所有记录,其中 zip_code 在 [...] 中,entity_url 在 [...] 中,然后从 records_to_insert 中删除匹配的数据”。
有没有办法让 SQLAlchemy 删除违反约束的记录?
最佳答案
My assumption that better to call
session.add(new_record)
multiple times and one timesession.commit()
.
您可能想重新审视这个假设。大量记录的批处理通常适用于多次提交——如果您有 10k 条记录并且您的代码在第 9,999 次引发异常怎么办?你将被迫重新开始。这里的核心问题是其中一条记录存在于数据库中而没有其余记录是否有意义。如果是这样,那么提交每个条目就没有问题(除了性能问题)。在这种情况下,您可以简单地捕获 IntegrityError 并调用 session.rollback()
继续记录列表。
无论如何,一个类似的问题是asked on the SQLA mailing list并由库的创建者 Mike Bayer 回答。他建议您自己从新记录列表中删除重复项,因为使用字典或集合很容易做到这一点。这可以像听写理解一样简单:
new_entities = { (entity['zip_code'], entity['url']): entity for entity in new_entities}
(这会选择最后一次看到的副本作为添加到数据库的副本。)
另请注意,他使用 SQLAlchemy 核心库来执行插入,而不是 ORM 的 session.add()
方法:
sess.execute(Entry.__table__.insert(), params=inserts)
如果您要处理大量记录(如在他的示例中,有 100,000 条记录),这是一个更快的选择。
关于python - SQLalchemy 添加多条记录和潜在的约束冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36591972/