Как избежать дублирования данных в базе данных PostgreSQL в Python

Я работаю над PostgreSQL и psycopg2. Попытка получить данные канала, которые обновляются каждые 10 минут, и сохранить содержимое этого канала в базе данных PostgreSQL. Моя цель - получить и распечатать эти данные из этой таблицы. Но столкнулся с проблемой, поскольку повторяющиеся данные также сохраняются в базе данных каждый раз, когда я запускаю этот скрипт из-за операции вставки в таблицу.

Чтобы решить эту проблему, я сделал ограничение первичного ключа столбца location_title в таблице Locations-musiq1, где я намереваюсь хранить данные фида. Но столкнулся с ошибкой.

Вот мой код:

import psycopg2
import sys
import feedparser
import codecs
import psycopg2.extensions


# Parsing data from Geofeed location feeds

data = feedparser.parse("some URL")
psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)



try:

    conn=psycopg2.connect("dbname='name' user='postgres' host='localhost'     password='abcds'")
    conn.set_client_encoding('UNICODE')


except:
    print "I am unable to connect to the database, exiting."
    sys.exit()
cur=conn.cursor()


for i in range(len(data['entries'])):
    cur.execute("INSERT INTO locations_musiq1(location, location_title) VALUES (%s, %s)",    (data.entries[i].title,data.entries[i].summary))
    conn.commit()
cur.execute("SELECT * FROM locations_musiq1;")
cur.fetchone()
for row in cur:
    print '   '.join(row[1:])


cur.close()
conn.close()

Моя ошибка после изменения столбца таблицы «locations_musiq1» «location_title» в качестве первичного ключа:

    Traceback (most recent call last):
      File "F:\JavaWorkspace\Test\src\postgr_example.py", line 28, in 
        cur.execute("INSERT INTO locations_musiq1(location, location_title) VALUES (%s, %s)",    (data.entries[i].title,data.entries[i].summary))
    psycopg2.IntegrityError: duplicate key value violates unique constraint "locations_musiq1_pkey"

Может у кого-нибудь есть идеи, как избавиться от этой проблемы?.. Заранее спасибо..


person rahman.bd    schedule 10.03.2010    source источник


Ответы (3)


Вы можете попробовать что-то вроде этого:

cur.execute("""
  INSERT INTO locations_musiq1(location, location_title) 
  SELECT %s, %s WHERE NOT EXISTS 
      (SELECT location_title FROM locations_musiq1 WHERE location_title=%s);
  """, (data.entries[i].title, data.entries[i].summary, data.entries[i].summary))
person ChristopheD    schedule 10.03.2010
comment
Спасибо за ответ!.. Но все же я столкнулся с проблемой, что данные канала не печатаются последовательно, они должны были печатать!.. Как они показывают данные (часть выходных данных моего сценария): X был в Лондоне (в 2010-03-10 14:46:35.0) X был в Лондоне(на 10.03.2010 15:30:35.0) X был в Лондоне (на 10.03.2010 15:19:35.0) X был в Лондоне (на 03.03.2010) 10 15:08:35.0 X был в Лондоне (на 10.03.2010 14:57:38.0) X был в Лондоне (на 10.03.2010 14:24:35.0) Итак, вы видите, что все они не появляются последовательно , а они должны были появиться серийно!.Вы имеете представление о том, чтобы все это серийно доставалось??!? - person rahman.bd; 10.03.2010
comment
После того, как вы вставили их в базу данных, просто используйте select * from locations_musiq1 order by mydatefield asc (или desc) - person ChristopheD; 10.03.2010

В вашем коде есть только INSERT, как вы думаете, что произойдет, когда вы получите те же данные во второй раз?

Ваше обновление завершается ошибкой, потому что вы пытаетесь вставить строку, которая имеет значение поля, идентичное тому, которое уже существует в столбце с уникальным ограничением.

Вам либо нужно сопоставить записи из фида с вашей таблицей и INSERT, UPDATE, DELETE в зависимости от ситуации. Где это уместно, определяется данными канала и причинами синхронизации. Или вы очищаете свою таблицу и каждый раз заполняете ее из ленты.

Чего вы пытаетесь достичь?

person MattH    schedule 10.03.2010

Рахман. Вы задаете второй вопрос в своем комментарии, который, вероятно, следует превратить в отдельный вопрос.

В любом случае, чтобы вернуть результаты в указанном порядке, вам нужно предложение order by. Я не вижу здесь столбца временных меток, но предполагаю, что данные вашего фида отформатированы в формате XML. Вы можете заказать по некоторому выражению xpath. Но если вы просто хотите, чтобы они были вставлены в том порядке, в котором они были вставлены, вы можете отсортировать по скрытому системному столбцу xmin, который является идентификатором транзакции операции вставки.

См. документацию по системным столбцам.

person Scott Bailey    schedule 10.03.2010