我正在尝试运行以下存储过程:
CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
AS
BEGIN
FOR i IN 1..5 LOOP
DBMS_OUTPUT.PUT('Try #' || i);
ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL;
END;
END;
/
并在changelog.xml中将其作为:
调用
<sql>CALL RETRY_TRANS_EXCEPTION();</sql>
我收到错误:
Liquibase update Failed: Migration failed for change set eldata-changelog.xml::2016-08-25-cn-01::Ch Will:Reason: liquibase.exception.DatabaseException: Error executing SQL CALL RETRY_TRANS_EXCEPTION(): ORA-06575: Package or function RETRY_TRANS_EXCEPTION is in an invalid state
我想要实现的是能够通过Liquibase运行存储过程并在其中循环。
感谢您的帮助Prashant。在我的案例中有用的是你的解决方案加上一个改变:
CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
AS
v_query varchar2(100);
BEGIN
FOR i IN 1..500 LOOP
DBMS_OUTPUT.PUT('Try #' || i);
v_query := 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NULL';
execute immediate v_query;
END loop;
END;
/
然后从更改日志中调用存储过程,如下:
<changeSet id="2016-08-25-cw-01" author="Ch Will">
<comment>
Testing retry logic on liquibase
</comment>
<sql>CALL RETRY_TRANS_EXCEPTION();</sql>
</changeSet>
答案 0 :(得分:3)
您无法调用它,因为该过程无法正确编译。返回并修复编译错误,然后重试。
以下是一些突出的错误:
for
循环应以end loop;
结尾,而不是end;
execute immediate 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL';
补充说明:我不明白你为什么要在循环中多次尝试执行相同的DDL语句。显然,您无法一遍又一遍地添加具有相同名称的相同列。您将收到运行时错误。
答案 1 :(得分:1)
SQL> CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
2 AS
3 BEGIN
4 FOR i IN 1..5 LOOP
5 DBMS_OUTPUT.PUT('Try #' || i);
6 ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL;
7 END;
8 END;
9 /
Warning: Procedure created with compilation errors
SQL> show err
Errors for PROCEDURE PRASHANT-MISHRA.RETRY_TRANS_EXCEPTION:
LINE/COL ERROR
-------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6/4 PLS-00103: Encountered the symbol "ALTER" when expecting one of the following: ( begin case declare end exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
是否需要修复:
CREATE OR REPLACE PROCEDURE RETRY_TRANS_EXCEPTION
AS
v_query varchar2(100);
BEGIN
FOR i IN 1..5 LOOP
DBMS_OUTPUT.PUT('Try #' || i);
v_query := 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL' ;
execute immediate v_query;
END loop;
END;
答案 2 :(得分:0)
PLSQL存储过程不能使用DDL语句,比如
alter table ...
所以
execute immediate ("...")
语句是必需的,因为实际上它创建了一个无法回滚的自主隐式转换