You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SQLcl批量加载多表时遇到错误立即终止执行

如何在SQLcl批量加载多表时遇到错误立即终止执行

我之前也踩过这个坑!你遇到的问题本质是SQLcl的load命令是客户端工具命令,不是标准SQL语句,所以你原来加的WHENEVER SQLERROR根本抓不到它的执行错误——这就是为什么tableB加载失败后,脚本还会自顾自跑tableC的原因。

核心解决思路就是:每个load命令执行后,手动检查SQLcl内置的错误状态变量,一旦发现非0错误码就立刻终止脚本。我给你整理了两种场景的解决方案,按需选用:


场景1:允许已成功加载的表保留,失败即终止后续操作

这种是贴合你最初需求的方案:前面的表加载成功就保留,只要某一步失败,立刻停下不加载后面的表。

修改后的完整脚本如下:

WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK
WHENEVER OSERROR EXIT SQL.SQLCODE ROLLBACK

-- 基础配置:不允许加载错误,加载前清空目标表
SET LOAD ERRORS 0
SET LOAD TRUNCATE ON

-- 加载tableA并检查错误
LOAD tableA input_tableA.csv
-- 把SQLcl内置的最后错误码赋值给自定义变量
VAR err_code NUMBER
BEGIN
  :err_code := SQL.LAST_ERROR_CODE;
END;
/
-- 错误检查:非0则终止脚本
IF :err_code != 0 THEN
  PROMPT 【错误】tableA加载失败,立即终止后续操作
  EXIT :err_code ROLLBACK
END IF

-- 加载tableB并检查错误
LOAD tableB input_tableB.csv
BEGIN
  :err_code := SQL.LAST_ERROR_CODE;
END;
/
IF :err_code != 0 THEN
  PROMPT 【错误】tableB加载失败,立即终止后续操作
  EXIT :err_code ROLLBACK
END IF

-- 加载tableC并检查错误
LOAD tableC input_tableC.csv
BEGIN
  :err_code := SQL.LAST_ERROR_CODE;
END;
/
IF :err_code != 0 THEN
  PROMPT 【错误】tableC加载失败,立即终止后续操作
  EXIT :err_code ROLLBACK
END IF

PROMPT 所有表加载完成,全部成功!

关键细节说明:

  • SQL.LAST_ERROR_CODE是SQLcl内置的绑定变量,专门记录最后一次客户端命令(比如load)的执行结果,0代表成功,非0代表失败。
  • 用PL/SQL块把这个内置错误码转存到自定义变量err_code里,再用SQLcl的客户端IF语句做判断,失败就用EXIT直接终止整个脚本。
  • 加PROMPT语句是为了在控制台输出明确的错误提示,避免你在几百个表的加载日志里漏看失败信息。

场景2:全量原子性加载(要么全成功,要么全回滚)

如果你的表之间有外键关联,或者要求数据的一致性,希望任何一个表加载失败,所有已加载的内容都回滚,那就要加上关闭自动提交的配置,脚本修改如下:

WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK
WHENEVER OSERROR EXIT SQL.SQLCODE ROLLBACK

-- 基础配置:不允许错误,清空目标表,关闭自动提交
SET LOAD ERRORS 0
SET LOAD TRUNCATE ON
SET LOAD AUTOCOMMIT OFF  -- 关键:关闭load命令的自动提交,统一控制事务

-- 加载tableA并检查
LOAD tableA input_tableA.csv
VAR err_code NUMBER
BEGIN
  :err_code := SQL.LAST_ERROR_CODE;
END;
/
IF :err_code != 0 THEN
  PROMPT 【错误】tableA加载失败,回滚所有操作并终止
  ROLLBACK;
  EXIT :err_code
END IF

-- 加载tableB并检查
LOAD tableB input_tableB.csv
BEGIN
  :err_code := SQL.LAST_ERROR_CODE;
END;
/
IF :err_code != 0 THEN
  PROMPT 【错误】tableB加载失败,回滚所有操作并终止
  ROLLBACK;
  EXIT :err_code
END IF

-- 加载tableC并检查
LOAD tableC input_tableC.csv
BEGIN
  :err_code := SQL.LAST_ERROR_CODE;
END;
/
IF :err_code != 0 THEN
  PROMPT 【错误】tableC加载失败,回滚所有操作并终止
  ROLLBACK;
  EXIT :err_code
END IF

-- 所有表加载成功,统一提交事务
COMMIT;
PROMPT 所有表加载完成,全部成功,事务已提交!

关键细节说明:

  • SET LOAD AUTOCOMMIT OFF会让load命令执行后不自动提交数据,所有加载的内容都在同一个事务里。
  • 任何一步失败时,执行ROLLBACK会把之前所有加载的内容全部撤销,避免数据库出现部分加载的不一致状态。
  • 只有所有步骤都成功,才会执行COMMIT把所有数据持久化到数据库。

额外小提示

如果要加载几百个表,重复写加载+检查的代码太麻烦,可以把单表加载逻辑封装成一个脚本片段,比如写一个load_single_table.sql,然后主脚本里循环调用它,能省不少事。

备注:内容来源于stack exchange,提问作者Eduard Uta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 07:42:58