Running PLSQL ( Oracle ) Stored Procedure in Liquibase error : Package or function X is in an invalid state

Running PLSQL ( Oracle ) Stored Procedure in Liquibase error : Package or function X is in an invalid state

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

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>

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

这里有几个错误对我来说很突出:

  1. for 循环应该以 end loop; 结束,而不是 end;
  2. 您不能在代码中直接包含 DDL 语句。您需要动态 SQL 才能从过程中执行 DDL 语句:execute immediate 'ALTER TABLE CIS_CASE ADD TEST01 varchar2(1) NOT NULL';

附加说明:我不明白您为什么要在循环内多次执行相同的 DDL 语句。显然,您将无法一遍又一遍地添加具有相同名称的相同列。您将收到运行时错误。

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;

PLSQL 存储过程不能使用 DDL 语句,例如

alter table ...

所以

execute immediate ("...") 

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