2016-08-23 38 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