Prevent error when dropping not existing sequences, creating existing users

前端 未结 5 895
北荒
北荒 2020-12-20 16:17

I have a bunch of sql scripts that create / drop sequences, users and other objects. I\'m running these scripts through liquibase, but they fail because oracle complains whe

相关标签:
5条回答
  • 2020-12-20 16:30

    Write a function do_ddl similar to this and catch all exceptions you want to catch:

    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;
    /
    
    0 讨论(0)
  • 2020-12-20 16:36

    Liquibase has a failOnError attribute you can set to false on changeSets that include a call that could fail.

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

    This allows you to have simple create user, create sequence, drop user, and drop sequence changeSets and if the statement throws an error because they users/sequences exist/don't exist they will still be marked as ran and the update will continue.

    The downside of this approach is that it will also mark them as ran and continue if they error for some other reason (bad permissions, connection failure, invalid SQL, etc.) The more accurate approach is to use preconditions, like this:

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

    There is no userExists precondition currently, but you can create custom preconditions or fall back to the precondition. See http://www.liquibase.org/documentation/preconditions.html for documentation

    0 讨论(0)
  • 2020-12-20 16:39

    I'd just use a PL/SQL anonymous block.

    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;
    /
    
    0 讨论(0)
  • 2020-12-20 16:44

    In my experience, based on Liquibase 3.5.1 behaviour, when using failOnError="false", the changeSet does not get recorded as 'RAN' if the operation failed. To me this seems a bug and Nathan's answer does not seem to be correct?

    The downside of this approach is that it will also mark them as ran and continue if they error for some other reason (bad permissions, connection failure, invalid SQL, etc.) The more accurate approach is to use preconditions, like this:

    I.e.: it does not mark them as ran!

    0 讨论(0)
  • 2020-12-20 16:44

    liquibase preconditions didn't check for existing sequences for me. So, after multiple attempts, I tried simple <changeSet id="test-id"><sql> DROP SEQUENCE IF EXISTS "TABLENAME_ID_seq"; </sql></changeSet>

    0 讨论(0)
提交回复
热议问题