2015-02-18 2 views
1

Я извлекаю json-файл из Интернета, который я хочу вставить в мою базу данных, используя peewee. Проблема в том, что некоторые из строк могут уже существовать в моей базе данных. Решение должно состоять в том, чтобы игнорировать или заменять повторяющиеся строки.Как я могу вставить несколько строк с помощью INSERT REPLACE в peewee?

Функция 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

Если это не представляется возможным в PeeWee, я бы также хотел бы знать. – Cecilia

+0

Я реализовал это для SQLite (который использует INSERT ИЛИ REPLACE INTO), поэтому добавление простого старого «REPLACE» может быть простым. Не стесняйтесь открывать билет github по адресу https://github.com/coleifer/peewee/issues/new – coleifer

ответ

2

Вы можете использовать on_conflict() или upsert() на своем InsertQuery.

on_conflict() добавит предложение SQL ON CONFLICT с заданным аргументом, но работает только с SQLite. upsert() в основном превращает запрос в REPLACE INTO на MySQL. Вам все равно нужно позвонить по телефону execute().

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:[email protected]/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» добавить «игнорировать» в выражении SQL. Мне очень помогли SQLAlchemy INSERT IGNORE