2015-03-19 5 views
1

Предположим, у меня есть две таблицы, старая статистика и статистика, у новой таблицы есть другое ограничение на столбце времени.Перенос данных с 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-04-01 00: 15: 00+ 01 '

Я нашел решение для SQLite с INSERT OR IGNORE (если произойдет нарушение ограничения, строки будут пропущены, и они будут продолжены), но не для POSTGRESQL.

Есть ли у вас какие-либо предложения?

+0

и возможный дубликат [Есть ли способ установить параметр, который приведет к продолжению сценария PostgreSQL, даже если есть ошибки?] (http: // stackoverflow. com/q/14908451/1288184) :) –

+0

@ SimoKivistö Ответ, указанный в вашем связанном вопросе, использует psql, но это не мой случай, так как я использую модуль psycopg2 с python. –

+0

@valentin_nasta Вы можете использовать 'DO' для запуска PL/pgSQL в обычном SQL: http://www.postgresql.org/docs/9.4/static/sql-do.html или создать сохраненную функцию. –

ответ

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

ОШИБКА: новая строка для отношения «статистика_2013_03» нарушает ограничение проверки «check_ts_2013_03» Состояние SQL: 23514 Действительно проверка_violation. Проблема в том, что она идет на ветку EXCEPTION при первом сбое. Но я хочу продолжить вставку и игнорировать те, которые не подходят. –

+0

Ops, извините. Я изменил свой ответ, еще раз проверьте. –

0

Что вы хотите делать с этими данными, хотите их объединить?

  • Для использования обеих таблиц я рекомендую использовать представление.
  • Если вы хотите вставить oldStatisticTime в statisticTime без изменения данных, вы можете удалить ограничение на триггер, не имея триггера, вставить данные и затем включить триггер.
+0

Я хочу перенести данные из старой таблицы в новую с выбором, но я не могу из-за ограничения. У меня нет спускового крючка на месте. Должен ли я добавить его? –

+0

Ограничение на таблицу состоит из таблицы, в которой «эти данные являются этой формой»; в то время как триггер (на вставке ei) говорит: «все новые данные будут соответствовать этим условиям» Вот почему я рекомендую добавлять триггер вместо ограничения, если вы сохраняете данные одинаково. Особенно, если ваш другой вариант состоит в том, чтобы обойти ваши собственные ограничения – jvDx

+0

Я понимаю, но, к сожалению, мне не разрешено удалить ограничение. Будет больше искать какое-то решение. Я мог бы перебирать строки и вычислять, на каком разделе должны соответствовать данные. –

Смежные вопросы