SSIS执行Oracle数据库DDL脚本报错ORA-00911及错误处理需求咨询
一、ORA-00911错误的根本原因
你遇到的ORA-00911: invalid character错误,最可能的触发点是脚本中的非注释格式分隔线,结合SSIS的执行逻辑导致的:
看你提供的脚本开头:
-------------------------------------------------------- -- DDL for Table ACCOUNT --------------------------------------------------------
第一行的分隔线没有以--开头,Oracle会把这堆连续的减号当作SQL语句尝试执行,而这显然是无效的SQL语法,因此直接抛出无效字符错误。
你说脚本在数据库中能成功执行,大概率是因为你用的数据库客户端(比如PL/SQL Developer、SQL*Plus)会自动跳过这类无意义的纯符号行,或者你手动执行时无意中移除了这些行。
另外也可以排查下SSIS任务的基础配置:
- 确认Execute SQL Task的
ResultSet属性设置为None(DDL语句不会返回结果集,选其他选项会触发错误); - 检查脚本文件的编码,避免UTF-8带BOM的格式(部分Oracle驱动对这种编码的特殊字符兼容不好)。
解决ORA-00911的步骤
批量清理脚本注释
把所有无--开头的分隔线改成注释格式,比如将--------------------------------------------------------替换为-- --------------------------------------------------------。如果有191个脚本,可以用Notepad++的批量替换功能(正则匹配^-{5,}$,替换为-- --------------------------------------------------------)快速处理。修正SSIS任务配置
- 确保Execute SQL Task的
ResultSet设为None; - 若使用OLEDB连接,将连接管理器的
RetainSameConnection设为True,提升批量执行的效率; - 确认
SQLSourceType选择File connection,并关联Foreach循环传递的脚本文件变量。
- 确保Execute SQL Task的
二、配置SSIS忽略错误并记录错误脚本
要实现「跳过错误脚本、继续执行、记录错误信息」,需要从任务错误处理和日志记录两方面配置:
1. 设置Execute SQL Task的错误容错
双击Execute SQL Task,切换到Execution Options选项卡:
- 将
FailPackageOnFailure和FailParentOnFailure都设为False,这样单个脚本执行失败不会终止整个包或循环; - 可以把
MaximumErrorCount设为一个大于191的数值,确保不会因为错误次数过多中断执行。
2. 记录错误脚本的详细信息
在Execute SQL Task的Event Handlers选项卡,添加OnError事件处理程序,用来捕获错误并记录:
方案1:用Script Task写入日志文件
假设你已经在Foreach循环中定义了变量@[User::CurrentScriptFile]存储当前脚本路径,在OnError事件的Script Task中:
- 设置
ReadWriteVariables为User::CurrentScriptFile, System::ErrorDescription; - 编写C#代码记录错误(示例):
using System; using System.IO; using Microsoft.SqlServer.Dts.Runtime; public void Main() { string scriptPath = Dts.Variables["User::CurrentScriptFile"].Value.ToString(); string errorDetails = Dts.Variables["System::ErrorDescription"].Value.ToString(); string logFile = @"D:\SSIS_Logs\DDL_Execution_Errors.log"; string logContent = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 出错脚本: {scriptPath}\n错误信息: {errorDetails}\n\n"; File.AppendAllText(logFile, logContent); Dts.TaskResult = (int)ScriptResults.Success; }
方案2:用Execute SQL Task写入数据库日志表
先创建一个日志表:
CREATE TABLE DDL_EXECUTION_LOG ( LOG_ID NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY, SCRIPT_FILE VARCHAR2(500), ERROR_TIME TIMESTAMP DEFAULT SYSTIMESTAMP, ERROR_MESSAGE VARCHAR2(1000) );
然后在OnError事件中添加Execute SQL Task,执行INSERT语句:
INSERT INTO DDL_EXECUTION_LOG (SCRIPT_FILE, ERROR_MESSAGE) VALUES (?, ?)
将参数分别映射到@[User::CurrentScriptFile]和@[System::ErrorDescription]变量。
3. 确保Foreach循环持续执行
进入Foreach循环容器的属性设置,将MaximumErrorCount设为0(表示不限制错误次数),这样即使多个脚本失败,循环也会处理完所有191个文件。
内容的提问来源于stack exchange,提问作者MansaSeyi

