Postgresql:使用 psycopg2 提供的 copy_expert 从 csv 文件导入表时发生外键冲突
Postgresql: Foreign key violations when importing tables from csv files using copy_expert offered by psycopg2
这里是问题陈述的再现。
两个表(例如 Tab1
和 Tab2
)的数据库模式已在名为(例如)schemas.ddl
的文件中给出。这两个表之间存在多个完整性约束(包括外键)。 data1.csv
和data2.csv
分别给出了这两个表的数据。我需要将这些 csv 文件中的数据放入表格中。
我是这样做的:
import psycopg2
conn = psycopg2.connect(database=postgres, user=postgres, host=localhost, port=5432)
cur = conn.cursor()
# Execute the schema, this works fine
cur.execute(open(schemas.ddl, "r").read())
files = ["data1.csv", "data2.csv"]
# Iterate through files to add data
for i in range(1,3):
copy_sql = "copy Tab"+str(i)+" from stdin with csv header delimiter as ',' null as 'null'"
with open(files[i-1],'r') as f:
cur.copy_expert(sql=copy_sql, file=f)
也就是说,我使用如图所示的copy_expert()
来复制第一个文件的数据,然后复制第二个文件的数据。但是,这会导致在输入数据时违反外键约束(和其他自定义约束)。
有没有办法在提交时检查输入数据的完整性,而不是在每个命令之后?我已经尝试 cur.execute("SET CONSTRAINTS ALL DEFERRED;")
但这并没有改变任何东西。
解决方案
作者:Anand Sowmithiran
只需将外键和约束设置为deferrable
。示例:
Foreign Key(A) references B deferrable;
或者如果您相信数据是正确的,只需禁用所有触发器并在复制后重新启用它们。
这些 FK 约束最初必须使用 DEFERRABLE 创建,然后才能使用 SET 命令延迟。或者,您可以关闭这 2 个表上的所有 triggers
,然后执行大容量复制操作,然后启用触发器。 PG 使用触发器来执行 FK 约束。
ALTER TABLE tab2 DISABLE TRIGGER ALL;
--run your program---
--and then enable triggers
ALTER TABLE tab2 ENABLE TRIGGER ALL;
这里是问题陈述的再现。
两个表(例如 Tab1
和 Tab2
)的数据库模式已在名为(例如)schemas.ddl
的文件中给出。这两个表之间存在多个完整性约束(包括外键)。 data1.csv
和data2.csv
分别给出了这两个表的数据。我需要将这些 csv 文件中的数据放入表格中。
我是这样做的:
import psycopg2
conn = psycopg2.connect(database=postgres, user=postgres, host=localhost, port=5432)
cur = conn.cursor()
# Execute the schema, this works fine
cur.execute(open(schemas.ddl, "r").read())
files = ["data1.csv", "data2.csv"]
# Iterate through files to add data
for i in range(1,3):
copy_sql = "copy Tab"+str(i)+" from stdin with csv header delimiter as ',' null as 'null'"
with open(files[i-1],'r') as f:
cur.copy_expert(sql=copy_sql, file=f)
也就是说,我使用如图所示的copy_expert()
来复制第一个文件的数据,然后复制第二个文件的数据。但是,这会导致在输入数据时违反外键约束(和其他自定义约束)。
有没有办法在提交时检查输入数据的完整性,而不是在每个命令之后?我已经尝试 cur.execute("SET CONSTRAINTS ALL DEFERRED;")
但这并没有改变任何东西。
解决方案
作者:Anand Sowmithiran
只需将外键和约束设置为deferrable
。示例:
Foreign Key(A) references B deferrable;
或者如果您相信数据是正确的,只需禁用所有触发器并在复制后重新启用它们。
这些 FK 约束最初必须使用 DEFERRABLE 创建,然后才能使用 SET 命令延迟。或者,您可以关闭这 2 个表上的所有 triggers
,然后执行大容量复制操作,然后启用触发器。 PG 使用触发器来执行 FK 约束。
ALTER TABLE tab2 DISABLE TRIGGER ALL;
--run your program---
--and then enable triggers
ALTER TABLE tab2 ENABLE TRIGGER ALL;