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>
您不能调用它,因为该过程没有正确编译。返回并修复编译错误,然后重试。
这里有几个错误对我来说很突出:
for
循环应该以 end loop;
结束,而不是 end;
- 您不能在代码中直接包含 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 ("...")
语句是必需的,因为实际上它创建了一个无法回滚的自主隐式转换
我正在尝试 运行 以下存储过程:
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>
您不能调用它,因为该过程没有正确编译。返回并修复编译错误,然后重试。
这里有几个错误对我来说很突出:
for
循环应该以end loop;
结束,而不是end;
- 您不能在代码中直接包含 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 ("...")
语句是必需的,因为实际上它创建了一个无法回滚的自主隐式转换