我有一堆sql脚本可以创建/删除序列,用户和其他对象。我通过liquibase运行这些脚本,但它们失败了,因为当我尝试删除不存在的序列或创建现有用户时,oracle会抱怨。
是否有预防错误的oracle方法?
某种东西
创建用户/序列(如果不存在)
删除User / Secuence(如果存在)
据我所知,我有以下选择:
任何想法/想法将不胜感激。
答案 0 :(得分:13)
Liquibase有一个failOnError属性,你可以在包含可能失败的调用的changeSets上设置为false。
<changeSet failOnError="false">
<createSequence sequenceName="new_sequence"/>
</changeSet>
这允许您拥有简单的创建用户,创建序列,删除用户和删除序列changeSet,如果语句因为用户/序列存在/不存在而抛出错误,它们仍将被标记为已运行且更新将继续。
这种方法的缺点是,如果由于某些其他原因(错误的权限,连接失败,无效的SQL等)出错,它也会将它们标记为已运行并继续运行。更准确的方法是使用前提条件,例如:
<changeSet>
<preconditions onFail="MARK_RAN"><not><sequenceExists/></not></preconditions>
<createSequence name="new_sequence"/>
</changeSet>
目前没有userExists前提条件,但您可以创建自定义前提条件或回退到前提条件。有关文档
,请参阅http://www.liquibase.org/documentation/preconditions.html答案 1 :(得分: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 :(得分: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;
/
答案 3 :(得分:1)
根据我的经验,基于Liquibase 3.5.1行为,当使用failOnError =“false”时,如果操作失败,则changeSet不会被记录为“RAN”。 对我来说,这似乎是一个错误,而Nathan的回答似乎不正确?
这种方法的缺点是它也会将它们标记为已运行 如果由于某些其他原因(错误的权限,它们出错)继续 连接失败,SQL无效等。)更准确的方法是 使用前置条件,如下:
即:它不会将它们标记为已运行!
答案 4 :(得分:1)
liquibase前提条件没有为我检查现有序列。因此,经过多次尝试,我尝试了简单的<changeSet id="test-id"><sql>
DROP SEQUENCE IF EXISTS "TABLENAME_ID_seq"; </sql></changeSet>