2015-03-19 73 views
1

假設我有兩個表,oldstatistics和統計,新表在時間列不同的約束。用INSERT INTO遷移數據,以便與約束PostgreSQL的侵犯

例如,新表具有以下contraint和舊錶中有違反數據:

CONSTRAINT check_ts_2013_03 CHECK (statistictime >= '2013-03-01 01:00:00+01'::timestamp with time zone AND statistictime < '2013-04-01 02:00:00+02'::timestamp with time zone)

違反假設他們有statistictime「2013年4月1日00及數據:15:00+ 01'

我發現了一些解決方案,SQLite與INSERT OR IGNORE(如果違反約束髮生的行將被跳過,它會繼續),但不是爲POSTGRESQL。

你有什麼建議嗎?

+0

以及可能的[有沒有辦法設置一個選項,即使存在錯誤也會導致PostgreSQL腳本繼續?](http:// stackoverflow。 com/q/14908451/1288184):) – 2015-03-19 09:58:10

+0

@SimoKivistö在你的鏈接問題中指定的答案是使用psql,但這不是我的情況,因爲我在python中使用psycopg2模塊。 – 2015-03-19 10:01:56

+0

@valentin_nasta您可以使用'DO'在普通SQL中運行PL/pgSQL:http://www.postgresql.org/docs/9.4/static/sql-do.html或創建一個存儲函數。 – 2015-03-19 10:03:31

回答

2

您可以用PLPGSQL功能和EXCEPTION塊(參見documentation)做到這一點:

CREATE or REPLACE FUNCTION insert_or_ignore() RETURNS VOID AS $$ 
DECLARE _value timestamp; 

BEGIN 
    FOR _value IN SELECT statistictime FROM oldstatistics LOOP 
    BEGIN 
     INSERT INTO statistics(statistictime) VALUES (_value); 
    EXCEPTION when check_violation THEN 
     -- DO NOTHING 
    END; 
    END LOOP; 
END; 
$$ 
LANGUAGE plpgsql; 

-- run the function 
SELECT insert_or_ignore(); 

你可能還需要插入等欄目,不僅statistictime。在這種情況下,您必須在DECLARE塊中聲明它們。 您還可以使用DO語句來完成,而不首先創建一個功能相同的事情(見documentation

DO $$ 
DECLARE _value timestamp;  
BEGIN 
     FOR _value IN SELECT statistictime FROM oldstatistics LOOP 
     BEGIN 
      INSERT INTO statistics(statistictime) VALUES (_value); 
     EXCEPTION when check_violation THEN 
      -- DO NOTHING 
     END; 
     END LOOP; 
END$$; 

我趕上這裏的「check_violation」異常,但檢查也都PostgreSQL的錯誤代碼,用於您希望發現其他類型錯誤的情況:error codes

+0

錯誤:關係「statistics_2013_03」的新行違反檢​​查約束「check_ts_2013_03」 SQL狀態:23514 確實是check_violation。問題在於它在EXCEPTION分支上第一次失敗。 但我想繼續插入和忽略,那些不適合的。 – 2015-03-19 10:18:38

+0

行動,對不起。我改變了我的答案,再次檢查。 – 2015-03-19 11:13:50

0

你想對這些數據做什麼,想合併它們?

  • 對於使用這兩個表,我建議使用視圖。
  • 如果要插入oldStatisticTime到statisticTime無需修改數據時,可以刪除約束至觸發,無法觸發,插入數據,然後啓用觸發器。
+0

我想遷移數據,從舊錶到新一個支持行選擇進入,但我不能因爲約束。 我沒有任何觸發器。 我應該添加一個嗎? – 2015-03-19 09:50:54

+0

對錶格的約束由一個表格表示'這些數據是這種形狀';同時觸發器(插入ei)表示'所有新數據都將符合這些條件' 這就是爲什麼我建議添加一個觸發器而不是一個約束條件,如果您保持數據相同的方式。特別是如果你的其他選擇是繞過你自己的約束 – jvDx 2015-03-19 10:31:29

+0

我明白,但不幸的是,我不允許刪除約束。將尋找更多的解決方案。我可能會遍歷行並找出數據適合哪個分區。 – 2015-03-19 10:50:32