2016-12-14 3 views
1

У меня есть существующий sqllite стол, к которому я обращаюсь с sqlalchemy. Я понял, что существует несколько дубликатов «случайных» чисел. Если я правильно понимаю, это кажется, что вы не можете добавить уникальное ограничение на таблицу после создания таблицы с sqllite, после удаления дубликатов с помощью:Предотвращение дублирования записей с sqlalchemy в существующей таблице sqlite

DELETE FROM mytable 
WHERE id NOT IN 
(
SELECT MIN(id) 
FROM judgements 
GROUP BY "case" 

Я решил использовать SQLAlchemy, чтобы предотвратить добавление дополнительных дубликатов. Я работаю с Scrapy и есть элемент трубопровода, который выглядит как:

class DynamicSQLlitePipeline(object): 

    def __init__(self,table_name): 
     db_path = "sqlite:///"+settings.SETTINGS_PATH+"\\data.db" 
     _engine = create_engine(db_path) 
     _connection = _engine.connect() 
     _metadata = MetaData() 
     _stack_items = Table(table_name, _metadata, 
          Column("id", Integer, primary_key=True), 
          Column("case", Text , unique=True), 
           ....) 
     _metadata.create_all(_engine) 
     self.connection = _connection 
     self.stack_items = _stack_items 



    def process_item(self, item, spider): 

     try: 
      ins_query = self.stack_items.insert().values(
      case=item['case'], 
      .... 
      ) 
      self.connection.execute(ins_query) 
     except IntegrityError: 
       print('THIS IS A DUP') 
     return item 

Единственное изменение, которое я сделал это, чтобы добавить уникальный = True в колонке «дело». Однако при тестировании все еще добавляются дубликаты/Как я могу заставить это работать?

ответ

1

Фрагмент кода ниже работает на моей стороне с версией python версии 2.7 и sqlalchemy версии 1.0.9 и sqlite версии 3.15.2.

from sqlalchemy import create_engine, MetaData, Column, Integer, Table, Text 
from sqlalchemy.exc import IntegrityError 


class DynamicSQLlitePipeline(object): 

    def __init__(self, table_name): 
     db_path = "sqlite:///data.db" 
     _engine = create_engine(db_path) 
     _connection = _engine.connect() 
     _metadata = MetaData() 
     _stack_items = Table(table_name, _metadata, 
          Column("id", Integer, primary_key=True), 
          Column("case", Text, unique=True),) 
     _metadata.create_all(_engine) 
     self.connection = _connection 
     self.stack_items = _stack_items 

    def process_item(self, item): 

     try: 
      ins_query = self.stack_items.insert().values(case=item['case']) 
      self.connection.execute(ins_query) 
     except IntegrityError: 
       print('THIS IS A DUP') 
     return item 

if __name__ == '__main__': 

    d = DynamicSQLlitePipeline("pipeline") 
    item = { 
     'case': 'sdjwaichjkneirjpewjcmelkdfpoewrjlkxncdsd' 
    } 
    print d.process_item(item) 

И выход для второго запуска будет, как:

THIS IS A DUP 
{'case': 'sdjwaichjkneirjpewjcmelkdfpoewrjlkxncdsd'} 

Я не вижу большой разницы между вашим кодом логики. Единственная разница может быть в версии, я думаю.

+0

Спасибо, я использую python 2.7 и sqlalchemy для 1.014. Мне интересно, если это связано с существующей таблицей, которую я здесь. Возможно, вы изначально создали таблицу с уникальным случаем? – user61629

+0

Я тестировал свой код, и когда я создаю новую таблицу, он работает так, как ожидалось, отклоняя дубликат. Но, как мне кажется, предыдущий стол не может быть изменен с помощью sqllite. – user61629

+0

Да, вам нужно удалить таблицу и создать ее снова. В противном случае вы можете использовать sqlalchemy-migrate для обновления схемы. – ichbinblau

Смежные вопросы