Предотвращение ошибки при удалении несуществующих последовательностей, создании существующих пользователей - PullRequest
7 голосов
/ 26 октября 2009

У меня есть куча сценариев sql, которые создают / удаляют последовательности, пользователей и другие объекты. Я запускаю эти сценарии через liquibase, но они терпят неудачу, потому что оракул жалуется, когда я пытаюсь удалить несуществующую последовательность или создать существующего пользователя.

Существует ли оракулярный способ предотвращения ошибок?

Что-то в этом роде

Создать пользователя / последовательность, если не существует

Удаление пользователя / безопасности, если существует

Насколько я знаю, у меня есть эти варианты:

  • Написать скрипт plsql
  • Использовать контексты ликвидазы.
  • Используйте предварительные условия для жидкой базы, но это будет означать слишком много работы.

Будем очень благодарны за любые мысли / идеи.

Ответы [ 5 ]

13 голосов
/ 27 октября 2009

Liquibase имеет атрибут failOnError, который можно установить в false на changeSets, который включает вызов, который может завершиться неудачей.

<changeSet failOnError="false">
   <createSequence sequenceName="new_sequence"/>
</changeSet>

Это позволяет вам просто создать пользователя, создать последовательность, удалить пользователя и удалить последовательность changeSets, и если инструкция выдает ошибку, потому что их пользователи / последовательности существуют / не существуют, они все равно будут помечены как запущенные и обновление будет продолжаться.

Недостатком этого подхода является то, что он также будет помечать их как запущенные и продолжит работу, если они выдадут ошибку по какой-либо другой причине (неправильные разрешения, сбой соединения, неверный SQL и т. Д.). Более точный подход заключается в использовании предварительных условий, например :

<changeSet>
   <preconditions onFail="MARK_RAN"><not><sequenceExists/></not></preconditions>
   <createSequence name="new_sequence"/>
</changeSet>

В настоящее время нет предусловия userExists, но вы можете создать пользовательские предусловия или вернуться к предусловию. См. http://www.liquibase.org/documentation/preconditions.html для документации

5 голосов
/ 26 октября 2009

Напишите функцию do_ddl, похожую на эту, и перехватите все исключения, которые вы хотите перехватить:

DECLARE
   allready_null EXCEPTION;
   PRAGMA EXCEPTION_INIT(allready_null, -1451);
BEGIN
   execute immediate 'ALTER TABLE TAB MODIFY(COL  NULL)';
EXCEPTION
   WHEN allready_null THEN
      null; -- handle the error
END;
/
2 голосов
/ 26 октября 2009

Я бы просто использовал анонимный блок PL / SQL.

begin
   for x in (select sequence_name
             from   user_sequences
              where sequence_name in ('SEQ1','SEQ2' ... 'SEQn'))
   loop
      execute immediate 'drop sequence '||x.sequence_name;
   end loop;
end;
/
1 голос
/ 26 декабря 2018
Предварительные условия

liquibase не проверяли существующие последовательности для меня. Итак, после нескольких попыток я попробовал простой <changeSet id="test-id"><sql> DROP SEQUENCE IF EXISTS "TABLENAME_ID_seq"; </sql></changeSet>

1 голос
/ 23 июля 2016

По моему опыту, основываясь на поведении Liquibase 3.5.1, при использовании failOnError = "false", changeSet не записывается как 'RAN', если операция не удалась. Мне это кажется ошибкой, и ответ Натана не кажется правильным?

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

Т.е .: он не помечает их как бегущих!

...