在Python中避免PostgreSQL数据库中的重复数据

2 投票
3 回答
3997 浏览
提问于 2025-04-15 20:14

我正在使用PostgreSQL和psycopg2,想要获取每10分钟更新一次的数据,并把这些数据存储在PostgreSQL数据库里。我的目标是从这个表中提取并打印这些数据。

但是每次运行这个脚本时,由于在表中插入数据,数据库里总是会存储重复的数据,这让我很困扰。

为了避免这个问题,我在表Locations-musiq1location_title列上设置了主键约束,打算用来存储我的数据。但我遇到了错误。

这是我的代码:

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"

有没有人能给我一些建议,帮我解决这个问题呢?谢谢!

3 个回答

1

Rahman,你在评论里问的第二个问题,可能应该单独提出来问。

无论如何,如果你想按照特定的顺序返回结果,就需要使用“order by”这个语句。我在这里没有看到时间戳的列,但我猜你的数据是用XML格式的。你可以根据某个xpath表达式来排序。不过,如果你只是想按照数据插入的顺序来排列,可以使用一个隐藏的系统列xmin,它是插入操作的事务ID。

可以查看关于系统列的文档。

2

你的代码里只有 INSERT,那么你觉得当你第二次获取相同的数据时会发生什么呢?

你的更新失败是因为你试图插入一行数据,而这行数据的某个字段值和已经存在的某行数据的字段值是一样的,而这个字段是有唯一性限制的。

你需要根据数据源中的内容来匹配你表格里的条目,然后根据需要进行插入、更新或删除。这里的“需要”是根据数据源的数据和你同步的目的来决定的。或者,你也可以每次都清空你的表格,然后从数据源重新填充数据。

你想要达到什么目的呢?

2

你可以试试这样的做法:

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))

撰写回答