2016-08-23 57 views
1

我使用PostgreSQL 9.5,我尝试插入使用BULK INSERT每天数百万行:PostgreSQL的日志到另一个表与冲突

INSERT INTO "tours" as cst ("adults","country_id", "price") 
VALUES (3, 129, 80), (2, 119,120) 
on conflict (adults, country_id) do 
    update set price = EXCLUDED.price, updated_at = now() 
    where excluded.price < cst.price 
RETURNING ID; 

如果价格较低,我会更新一行。我想为未更新的日志价格添加else条件。事情是这样的:

INSERT INTO "tours" as cst ("adults","country_id", "price") 
VALUES (3, 129, 80), (2, 119,120) 
on conflict (adults, country_id) 
    case when excluded.price < cst.price 
     then 
     do update set price = EXCLUDED.price, updated_at = now() 
     else 
     INSERT INTO "tours_price_logging" (price, created_at) 
     values (EXCLUDED.price, now()) end; 

但我有错误这种情况:

ERROR: syntax error at or near "case" 

我想从插入取出条件where excluded.price < cst.price,并将这个逻辑trigger,但后来我会更新行的价格与价值从tours_price_logging和价格可能更多然后当前。

所以,我想使用upsert和批量插入日志记录。

回答

0

您只需将您的CASE移入UPDATE。 “ON CONFLICT”可以做两件事之一,没有任何事情或更新。

...ON CONFLICT (adults, country_id) UPDATE SET price = CASE WHEN ... ; 
2

你需要一个触发:

create or replace function before_update_on_tours() 
returns trigger language plpgsql as $$ 
begin 
    if new.price >= old.price then 
     insert into tours_price_logging (price, created_at) 
     values (new.price, now()); 
     return null; 
    end if; 
    return new; 
end $$; 

create trigger before_update_on_tours 
before update on tours 
for each row execute procedure before_update_on_tours(); 

当一个新的价格是不是比老触发插入行的记录表并返回null,所以没有更新,将在完成低旅行团。 与触发您的查询应该是这样的:

insert into tours as cst (adults,country_id, price) 
values (3, 129, 80), (2, 119, 90) 
on conflict (adults, country_id) do 
    update set price = excluded.price, updated_at = now() 
returning id; 
+0

我注意到,有时我需要更新的价格定价,更多的则电流(从另一个查询)。价格已过期,当它过期时,我从'tours_price_logging'获得新价格,而且价格可能会更高。所以,这个触发器并不适用于我所有的情况。 –

+0

或者我可以跳过查询中的触发器执行? –

+0

您可以使用['when(condition)'](https://www.postgresql.org/docs/current/static/sql-createtrigger.html)子句创建* conditional * trigger。您应该找到一个列,您可以在其中设置条件以跳过触发器执行。 – klin