2014-01-14 106 views
0

我正试图在我的项目中实现数据库抽象,但现在我在PostgreSQL中做了批量INSERT。我的项目是在C#中,我使用PostgreSQL 9.3和npgsql.dll 2.0.14。如何在没有主键冲突的情况下执行PostgreSQL Bulk INSERT

对于Microsoft SQL Server,我通过连接所有语句,然后执行的ExecuteNonQuery简单地做批量插入:通过选择 -

IF NOT EXISTS (SELECT id FROM table WHERE id = 1) INSERT INTO table (id) VALUES (1); 
IF NOT EXISTS (SELECT id FROM table WHERE id = 2) INSERT INTO table (id) VALUES (2); 
IF NOT EXISTS (SELECT id FROM table WHERE id = 3) INSERT INTO table (id) VALUES (3); 

尽管IF-NOT-EXISTS子句可以在PostgreSQL的取代在那里,这种方法遗憾的仍然不起作用 - 因为PostgreSQL中的每一条语句都是单独提交的。

因此,我搜索了另一个解决方案,并发现使用COPY命令和NpgsqlCopySerializer/NpgsqlCopyIn一起正常地“流”批量数据的方法。但是现在我总是得到主键违例错误 - 因为EXISTS/WHERE子句似乎不能与COPY语句一起使用。

我真的很想避免一个一个地插入INSERT,因为这会极大地减慢我的应用程序,所以我希望任何人都能解决这个问题!

回答

1

通常对于这种情况,我会有一个单独的临时表,它没有PK约束,我将使用COPY来填充(假设数据的格式为COPY )。然后我会做这样的事:

insert into table 
select a.* 
from staging a 
where not exists (select 1 
        from table 
        where a.id = b.id) 

这种方法是不是离你的原始设计太远。

我不完全明白你的问题的一部分,然而,这并不甚至似乎你的问题完全相关:

这种做法可惜还是不行 - 因为每一个 声明在postgreSQL中是分开承诺的。

根本不是这样,不适用于任何RDBMS。当然,自动提交可能会在您的客户端启用,但这并不意味着postgres单独提交每条语句,并且您不能禁用自动提交。这种方法是有效的:

begin; 
insert into table (id) select 1 where not exists (select 1 from table where id = 1); 
insert into table (id) select 2 where not exists (select 1 from table where id = 2); 
insert into table (id) select 3 where not exists (select 1 from table where id = 3); 
commit; 

正如你指出的,但是,如果你有比这样的言论,你会很快地打一些性能问题的屈指可数。

+0

嗨yieldfalsehood,你让我的一天!实际上BEGIN-COMMIT是我错过了使我的代码工作(与SELECT-WHERE-NOT-EXISTS一起) – Loonis

相关问题