在大型 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
并继续执行而不使包失效。
实际上,没有。
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,那么您就知道,如果要修改该表的结构,则需要修改该包的实现。 如果您愿意,您可以使这些实现向后兼容,以便调用代码至少可以继续编译而不进行任何更改。