9

我有一堆创建/删除序列、用户和其他对象的 sql 脚本。我正在通过 liquibase 运行这些脚本,但它们失败了,因为当我尝试删除不存在的序列或创建现有用户时,oracle 会抱怨。

有没有一种预言机方法来防止错误发生?

类似的东西

如果不存在则创建用户/序列

如果存在则删除用户/安全

据我所知,我有以下选择:

  • 写一个plsql脚本
  • 使用 liquibase 上下文。
  • 使用 liquibase 前提条件,但这意味着工作量太大。

任何想法/想法将不胜感激。

4

5 回答 5

19

Liquibase 有一个 failOnError 属性,您可以在包含可能失败的调用的 changeSet 上将其设置为 false。

<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

于 2009-10-26T21:48:08.703 回答
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;
/
于 2009-10-26T15:50:07.890 回答
2

我只是使用 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;
/
于 2009-10-26T18:51:31.580 回答
1

根据我的经验,根据 Liquibase 3.5.1 的行为,使用 failOnError="false" 时,如果操作失败,changeSet 不会记录为“RAN”。对我来说,这似乎是一个错误,内森的回答似乎不正确?

这种方法的缺点是它也会将它们标记为已运行,如果它们由于某些其他原因(错误的权限、连接失败、无效的 SQL 等)而出错,它也会继续。更准确的方法是使用前置条件,如下所示:

即:它不会将它们标记为已运行!

于 2016-07-23T19:51:03.997 回答
1

liquibase 前提条件没有为我检查现有序列。所以,经过多次尝试,我尝试了简单<changeSet id="test-id"><sql> DROP SEQUENCE IF EXISTS "TABLENAME_ID_seq"; </sql></changeSet>

于 2018-12-26T16:10:59.270 回答