处理ORA-00947并继续在PL/SQL包中执行

问题描述 投票:0回答:1

问题:

在大型 PL/SQL 包中,我有多个

INSERT
语句,有时当值的数量与列不匹配时会遇到
ORA-00947: not enough values
错误。我想捕获此错误,记录它,并允许包继续进行后续操作(例如插入其他表),而不会使整个包失效。

代码:

CREATE TABLE RFTB_DAILY_GL_BAL (
    col1 NUMBER,
    col2 VARCHAR2(20),
    col3 DATE
);

DECLARE
BEGIN
    BEGIN
        INSERT INTO RFTB_DAILY_GL_BAL-- (col1, col2, col3)
        SELECT 1 FROM dual; -- Causes ORA-00947
    EXCEPTION
        WHEN OTHERS THEN
                dbms_output.put_line('error found: ' || SQLERRM);
          
    END;

    -- Proceed to next insertion
    dbms_output.put_line('Continuing to next step...');
    -- Simulate another operation
    INSERT INTO another_table (col1, col2) VALUES ('test', SYSDATE);

END;
/

问题:

这是一种在不停止整个 PL/SQL 包执行的情况下捕获和处理

ORA-00947
的有效方法吗?有什么建议可以改进这种方法吗?

原因:

我正处于开发阶段,我经常根据不断变化的需求创建或删除专栏(是的,我知道这并不理想,但较短的期限使其成为必要)。因此,即使我在

INSERT
中指定列,我也不能依赖列结构保持不变。我需要捕获
ORA-00947: not enough values
并继续执行而不使包失效。

sql database oracle plsql
1个回答
0
投票

实际上,没有。

ORA-00947 是一个 PL/SQL 编译错误。 您发布的代码无法编译。 由于它无法编译,因此无法运行,因此它永远无法到达异常处理程序。 您无法使用运行时异常处理程序捕获编译错误。

从技术上来说,是的。

话虽如此,您可以使用动态 SQL 将编译推迟到运行时,这会将编译错误更改为您可以捕获的运行时错误。 实际上,您不想这样做,因为它会使编写、调试和维护代码变得更加耗时。

所以你可以做类似的事情

DECLARE
BEGIN
    BEGIN
        EXECUTE IMMEDIATE 
          'INSERT INTO RFTB_DAILY_GL_BAL ' ||
          '  SELECT 1 FROM dual; '-- Causes ORA-00947
    EXCEPTION
        WHEN OTHERS THEN
                dbms_output.put_line('error found: ' || SQLERRM);
          
    END;

    -- Proceed to next insertion
    dbms_output.put_line('Continuing to next step...');
    -- Simulate another operation
    INSERT INTO another_table (col1, col2) VALUES ('test', SYSDATE);

END;
/

但实际上,将您想要在运行时捕获的所有内容移至动态 SQL 不太可能是一个好的选择。

编写更模块化的代码更有可能为您提供更好的服务。 例如,如果您有一个包可以处理

RFTB_DAILY_GL_BAL
上的所有 DML,那么您就知道,如果要修改该表的结构,则需要修改该包的实现。 如果您愿意,您可以使这些实现向后兼容,以便调用代码至少可以继续编译而不进行任何更改。

© www.soinside.com 2019 - 2024. All rights reserved.