Заполнение базы данных в PostgreSQL - PullRequest
3 голосов
/ 30 марта 2012

Следующая ссылка в руководстве по документации PostgreSQL http://www.postgresql.org/docs/8.3/interactive/populate.html гласит, что для отключения автоматической фиксации в postgreSQL вы можете просто поместить все операторы вставки в BEGIN; и COMMIT;

Однако я испытываю трудности с фиксацией любых исключений, которые могут произойти между BEGIN; COMMIT; и если происходит ошибка (например, попытка вставить дублирующийся PK), у меня нет возможности явно вызывать команды ROLLBACK или COMMIT. Хотя все операторы вставки автоматически откатываются, PostgreSQL все еще ожидает явного вызова команд COMMIT или ROLLBACK, прежде чем он сможет считать транзакцию завершенной. В противном случае сценарий должен ожидать истечения времени ожидания транзакции, и любые последующие операторы вызовут ошибку.

В хранимой процедуре вы можете использовать предложение EXCEPTION, чтобы сделать это, но это не относится к моим обстоятельствам выполнения массовых вставок. Я пробовал это, и блок исключения не работал для меня, потому что следующий оператор (ы), выполненный после того, как ошибка имеет место, не выполняется с ошибкой:

ERROR:  current transaction is aborted, commands ignored until end of transaction block

Транзакция остается открытой, так как она не была явно завершена с вызовом COMMIT или ROLLBACK;

Вот пример кода, который я использовал для проверки этого:

BEGIN;
  SET search_path TO testing;
  INSERT INTO friends (id, name) VALUES (1, 'asd');
  INSERT INTO friends (id, name) VALUES (2, 'abcd');
    INSERT INTO friends (id, nsame) VALUES (2, 'abcd'); /*note the deliberate mistake in  attribute name and also the deliberately repeated pk value number 2*/
EXCEPTION /* this part does not work for me */
    WHEN OTHERS THEN
        ROLLBACK;   
COMMIT;

При использовании такой техники действительно ли я должен гарантировать, что все утверждения будут успешными? Почему это так? Разве нет способа перехватить ошибки и явно вызвать откат?

Спасибо

Ответы [ 2 ]

2 голосов
/ 30 марта 2012

если вы делаете это между началом и фиксацией, то все автоматически откатывается в случае исключения. Выдержка из размещенного вами URL: «Дополнительным преимуществом выполнения всех вставок в одной транзакции является то, что если при вставке одной строки произойдет сбой, вставка всех строк, вставленных до этой точки, будет отменена, поэтому вы не застрянете с частично загруженными данными. «

0 голосов
/ 30 марта 2012

Когда я инициализирую базы данных, то есть создаю серию таблиц / представлений / функций / триггеров / и т. Д. и / или загружая исходные данные, я всегда использую psql, и это Переменные для управления потоком. Я всегда добавляю:

\set ON_ERROR_STOP

к началу моих скриптов, поэтому всякий раз, когда я нажимаю какое-либо исключение, psql отменяется. Похоже, это может помочь и в вашем случае.

И в случаях, когда мне нужно выполнить некоторую обработку исключений, я использую блоки анонимного кода , например:

DO $$DECLARE _rec record;
BEGIN
FOR _rec IN SELECT * FROM schema WHERE schema_name != 'master' LOOP
    EXECUTE 'DROP SCHEMA '||_rec.schema_name||' CASCADE';
END LOOP;
EXCEPTION WHEN others THEN
NULL;
END;$$;
DROP SCHEMA master CASCADE;
...