Python 仅将唯一记录导入PostgreSQL

Python 仅将唯一记录导入PostgreSQL,python,postgresql,csv,duplicates,upsert,Python,Postgresql,Csv,Duplicates,Upsert,我正在尝试使用Python将CSV文件导入PostgreSQL。我想告诉Python只导入CSV文件中不包含重复项的记录/数据行(只有第一条唯一的构建器记录)。我已经附上了我用来在CSV文件中查找重复项的代码。我是编程新手,请原谅我缺乏经验 import csv import psycopg2 database = psycopg2.connect (database = "***", user="***") cursor = database.cursor() delete = """Dr

我正在尝试使用Python将CSV文件导入PostgreSQL。我想告诉Python只导入CSV文件中不包含重复项的记录/数据行(只有第一条唯一的构建器记录)。我已经附上了我用来在CSV文件中查找重复项的代码。我是编程新手,请原谅我缺乏经验

import csv
import psycopg2

database = psycopg2.connect (database = "***", user="***")

cursor = database.cursor()
delete = """Drop table if exists "Real".Noduplicates"""
print (delete)

mydata = cursor.execute(delete)

cursor.execute("""Create Table "Real".Noduplicates
            (UserName varchar(55),
            LastUpdate timestamp,
            Week date,
            Builder varchar(55),
            Traffic integer
            );""")

print "Table created successfully"

csv_data = csv.reader(file('SampleData2.csv'))

already_seen = set()

next(csv_data)

for row in csv_data:
    builder = row[3]
    if builder in already_seen:
        print('{} is a duplicate builder'.format(builder))
    else:
        print('{} is a new builder'.format(builder))
        already_seen.add(builder)

for row in csv_data:

    cursor.execute("""INSERT INTO "Real".Noduplicates (UserName, LastUpdate, Week, Builder, Traffic)"""\
                    """VALUES (%s,%s,%s,%s,%s)""",
           row)

cursor.close()
database.commit()
database.close()

print "CSV Imported"

相反,使用
COPY
(速度更快)将所有行导入临时表,然后使用
SELECT distinct…
SELECT distinct ON(builder)
或使用聚合函数将
一个distinct集插入目标表。查找重复项是任何RDBMS的一项强项

相关代码示例:

,在逐个插入行时,Postgres 9.5中的新UPSERT和所有5列上的
唯一
索引就是您所需要的:

但是请注意
NULL
值的特殊作用(在SQL中,这些值永远不会被认为是相等的):

如果列
builder
是识别重复项所需的全部,只需定义该列
UNIQUE

。。。
生成器varchar(55)唯一值不为空,
...
并使用简单的向上插入:

插入到“Real”中。节点副本(用户名、上次更新、周、生成器、流量)
值(%s,%s,%s,%s,%s)
论冲突论(建设者)无所作为;
最好不要在Postgres中使用CaMelCase名称顺便说一句:


我会将您的表生成器更改为唯一。这意味着您的数据库将拒绝此密钥的所有副本。然后循环遍历数据,尝试插入每条记录,如果失败,则捕获异常。让数据库为你做这项工作。@Hannu:没错。使用新的UPSERT(
INSERT…ON CONFLICT…
),您甚至不会遇到异常。谢谢Erwin,我能告诉Python只将第一个唯一的构建器记录发送到数据库中吗?我想消除Python中的重复。@Pythoner:Python如何在不查找的情况下知道表中有哪些行?数据源是CSV文件,是否可以告诉Python只导入唯一的生成器记录,然后插入到postgreSQL中?@Pythoner:当然,可能。但您可能会尝试重新实现Postgres用于识别集合中重复项的复杂算法。如果“生成器”字段在数据库中是唯一的,则相同密钥的所有插入都将失败。如果出于某种原因希望在程序中执行此操作,则需要按照此答案中的指示进行选择。我建议您使用您拥有的强大工具(关系数据库),而不是试图与之进行激烈的斗争。如果您的表很大或变得很大,那么允许DB处理重复项将比在Python中处理重复项更有效,因为数据库会索引,而不是在列表中进行顺序搜索等。