2009-10-26 2 views
6

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

Есть ли способ оракула предотвратить ошибки?

Нечто подобное

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

отброшенных пользователя/Secuence если существует

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

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

Любые мысли и идеи будут очень признательны.

ответ

13

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

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

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

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

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

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

+0

Я считал предварительные условия, но остается одно сомнение: если у меня есть N, создайте инструкции последовательности, я должен создать равное количество наборов изменений? – Tom

+2

Да, вы должны. ChangeSets пытаются быть транзакционными, но базы данных часто автоматически фиксируются на вызовах DDL, таких как создание последовательности. Таблица базы данных, которую Liquibase использует для отслеживания того, что changeSets запускала, просто отслеживает все выполняемые переменные, поэтому, если у вас есть 15 запросов на создание последовательности в одном наборе changeSet, и по какой-то причине восьмой из них выдает ошибку, обновление Liquibase не будет выполнено на из-за этой ошибки, и с этого момента changeSet всегда будет терпеть неудачу, потому что первая последовательность уже существует. Таким образом, лучший подход заключается в том, чтобы иметь один вызов DDL для changeSet. –

+0

синтаксис для Liquibase 3.4.2 изменился, атрибут name теперь является "sequenceName" – chrismarx

5

Написать функцию 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

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

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

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

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

I.e .: Это не означает, что они побежали!

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