2012-03-30 8 views
3

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

Однако мне трудно получить любые исключения, которые могут произойти между 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

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

+0

Все заявления откатываются, и это право; Однако транзакция не считается завершенной, и любые заявления, которые планируется выполнить после этого, не выполняются, потому что вышеупомянутая ошибка возникает с каждым новым выражением; – prince

+0

Что вы планируете делать? Если есть другие данные, которые должны быть вставлены независимо от предыдущих сбоев, вы должны добавить их в другой блок begin-commit. – FooLman

0

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

\set ON_ERROR_STOP 

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

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

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; 
Смежные вопросы