在Liquibase中运行PLSQL(Oracle)存储过程错误:包或函数X处于无效状态

时间:2016-09-09 01:03:57

标签: oracle plsql liquibase

我正在尝试运行以下存储过程:

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>

3 个答案:

答案 0 :(得分:3)

您无法调用它,因为该过程无法正确编译。返回并修复编译错误,然后重试。

以下是一些突出的错误:

  1. for循环应以end loop;结尾,而不是end;
  2. 您不能直接在代码中使用DDL语句。您需要动态SQL来执行过程中的DDL语句:execute immediate 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL';
  3. 补充说明:我不明白你为什么要在循环中多次尝试执行相同的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 ("...") 

语句是必需的,因为实际上它创建了一个无法回滚的自主隐式转换