我正在使用peewee从在线检索我要插入数据库的json文件。问题是我的数据库中可能已存在某些行。解决方案应该是忽略或替换重复的行。
InsertQuery
函数支持添加多行,但我无法弄清楚如何抑制实例已存在的错误或替换现有实例。
从空数据库测试开始,我运行以下代码
from peewee import *
from peewee import InsertQuery
database = MySQLDatabase('test', **{'password': 'researchServer', 'user': 'root'})
class BaseModel(Model):
class Meta:
database = database
class Image(BaseModel):
url = CharField(unique=True)
database.connect()
database.create_tables([Image])
images= [{'url': 'one'}, {'url':'two'}]
try:
image_entry = InsertQuery(Image, rows=images)
image_entry.execute()
except:
print 'error'
这不会产生任何错误,并成功添加了一个'和'两个'到我的桌子。
如果我再跑,
images= [{'url':'three'}, {'url': 'one'}, {'url':'four'}]
try:
image_entry = InsertQuery(Image, rows=images)
image_entry.execute()
except:
print 'error'
执行功能会抛出一个错误,而且三个'或者四个'被添加到数据库中。
我想一个解决方案是在将每行添加到数据库之前检查每一行,但这似乎效率更低。
答案 0 :(得分:2)
您可以在InsertQuery
上使用on_conflict()
或upsert()
。
on_conflict()
将使用给定的参数添加SQL ON CONFLICT
子句,但仅适用于SQLite。 upsert()
基本上将查询转换为MySQL上的REPLACE INTO
。您仍然需要在{。<}后调用execute()
。
答案 1 :(得分:1)
我无法在peewee中找到解决方案,但这是我为SQLAlchemy编写的解决方案。
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy import create_engine
#Make the table
metadata = MetaData()
image = Table('image', metadata,
Column('url', String(250), primary_key=True))
db = create_engine('mysql://root:researchServer@localhost/test3')
metadata.create_all(db)
conn = engine.connect()
#Insert the first set of rows
images = [{'url': 'one'}, {'url': 'two'}]
inserter = db.image.insert()
conn.execute(inserter, images)
#Insert the second set of rows with some duplicates
images = [{'url': 'three'}, {'url': 'one'}, {'url':'four'}]
try:
inserter = db.image.insert().prefix_with("IGNORE")
conn.execute(inserter, images)
except:
print 'error'
关键是使用'prefix_with'方法将'ignore'添加到SQL表达式中。 SQLAlchemy INSERT IGNORE
给了我很大的帮助答案 2 :(得分:1)
Image.insert_many(images).upsert(True).execute()