☰
在Informatica Mapping中用pre SQL调用存储过程的完整指南
2026/10/22 1:03:38 网站建设 项目流程

简介:Informatica调用存储过程是数据集成项目中的常见需求,这份图文流程资料正是为数据仓库工程师、ETL开发人员及需要快速上手的Informatica初学者准备的,解决在实际Mapping中如何正确通过pre SQL调起存储过程、传递参数并验证结果的问题。资源打包为1个docx文档,体积约180KB,以分步截图配合文字说明的方式,完整呈现从新建Mapping、右键目标表进入编辑、切换属性选项卡,到在pre SQL栏写入调用脚本、使用变量替换入参、保存并运行的全部关键操作。正文中附有界面截图与操作标注,可以边看边练,适合作为日常查阅的速查手册。目前已有976人学习下载,口碑经过验证。资料同时介绍了存储过程在批量数据处理、权限控制、数据一致性保障上的优势,以及数据迁移、数据同步、报表生成等典型应用场景,帮助读者不仅会操作,也能理解原理,并直接复用到实际集成任务中。

1. 把存储过程塞进Informatica Mapping:这个操作为什么值得学

刚开始做ETL的时候,我一度以为所有数据清洗都必须在Mapping里用转换器铺出来,直到有一次看同事排障,发现他直接在目标表属性里写了一句CALL语句,整个预处理流程瞬间少了一半。Informatica调用存储过程算不上什么黑科技,但它非常能解决实际问题:源表数据又脏又大,只靠Mapping里一行行转换,性能扛不住,而数据库端已经有一套成熟的存储过程逻辑,没必要用ETL工具再重写一遍。适合正在做数据仓库同步、批量数据迁移的开发者,尤其是手里已经有存储过程资产、只想把Informatica当调度器的人。把pre SQL字段用好,相当于给Mapping加了一个数据库端的执行开关,逻辑不变,成本极低。

2. 存储过程与pre SQL的执行边界:时机、顺序和选型依据

在动手写任何配置之前,先把pre SQL这个机制讲透。它不是Informatica独有的概念,但很多人把它当普通SQL执行入口,结果踩了执行顺序的坑。这一节讨论的不是语法,而是“什么时候跑、跑在哪个阶段、能不能替代Mapping逻辑”。

2.1 存储过程能替Mapping扛下哪些活

存储过程不是新鲜概念。它是一组为了完成特定功能而预编译的SQL语句集合,保存在数据库端,调用时只需要一条CALL或EXEC。在ETL流程里,存储过程出场的场景通常有三个:批量清洗,比如对源表里重复的历史记录做去重标记,或者把明显超出取值范围的数据打上异常标识;临时表准备,把多张业务表join好落到一张临时表,再让Mapping从这张临时表读取;周期性归档,把三个月前的数据搬到归档表,同时在主表里做删除。这类操作如果放在Mapping里做,每次都要搬运大量旧数据,网络开销很痛。

这些操作有一个共同特点:它们都是集合级别的操作,用SQL表达最高效。存储过程在数据库端执行,不需要把大量原始数据拉到Informatica的引擎里做处理。如果非要在Mapping里拆成一个个Source Qualifier、Expression、Lookup,开发效率低,跑起来性能也难看,尤其在大表场景下,行级转换的吞吐量远远跑不赢数据库端的批量SQL。所以团队里如果已经有现成存储过程,最合理的做法是在Informatica里直接复用它,而不是在Mapping里重写一遍。

边界要拎清楚:存储过程负责数据库端集合操作,Mapping负责行级转换、字段映射、过滤和连接。两者不是一个层级的替代品。

2.2 pre SQL究竟在什么时候执行

所谓pre SQL,是目标表属性里的一个配置项,含义是“加载前执行的SQL”。执行顺序拆开看:会话启动后,先做源端读取,然后进入目标端执行pre SQL脚本,接着开始写入目标表,最后执行post SQL。也就是说,pre SQL的执行时点,是在目标表数据变化之前。这一点很关键,因为很多人会把pre SQL理解成“会话前执行”,但更准确的说法是“目标表加载前执行”。

如果同一个Mapping里有多个目标表,每个目标表都有自己的pre SQL和post SQL,它们各自在各自的队列里执行。我一般习惯在pre SQL里放两类操作:清空目标表的存量数据、调用存储过程准备加载所需的数据。这两类操作都必须发生在写入之前。post SQL则相反,它做的是加载之后的收尾动作,比如更新汇总表、记录日志。两者之间隔着一次目标表写入,理解了这个顺序,就不会把该放在post SQL的语句写到pre SQL里。

2.3 选型:什么时候该用pre SQL调存储过程,什么时候不该用

选型标准就一条:看操作是集合级还是行级。集合级操作交给存储过程,行级转换留在Mapping里。举一个组合例子:目标表需要先被存储过程清空并插入一批汇总数据,然后Mapping再从另外一张源表读取明细写入目标表。这个清空和汇总的动作打包成一个存储过程,在pre SQL里调用;而明细数据的字段映射、类型转换,还是用Mapping的转换器。

反过来,如果要做的是根据每行数据的状态字段去查维表,再决定目标值,这种逐行查询就不适合写成存储过程。每次调用都有上下文切换开销,Mapping里的Lookup转换器反而更合适。还有一种常见误用,是在pre SQL里放一个耗时的全量更新,但这个全量更新和Mapping的写入逻辑没有先后依赖,完全可以放到post SQL或者单独调度,没必要阻塞加载阶段。

2.4 动手前先确认存储过程的访问权限

在配置pre SQL之前,我建议先做一步验证:确认Informatica要用的数据库账号有没有存储过程的执行权限。权限不足时,作业会在pre SQL阶段直接挂掉,而且报错有时候很隐晦。可以登录数据库客户端,用一条SQL查看存储过程是否存在,再直接执行一遍调用语句,确认能正常返回。

-- 查看指定存储过程是否存在(不同数据库语法略有差异) SELECT object_name, status FROM user_objects WHERE object_type = 'PROCEDURE' AND object_name = 'SP_CLEAN_DATA';

这条SQL在多数数据库里都能用,查出来status为VALID,说明存储过程本身没有问题。然后手动执行一遍CALL,确认无异常。这一步能筛掉一大半“为什么Mapping跑不过”的玄学问题。权限确认完,再回到Informatica里配pre SQL,思路就会清晰很多。

2.5 pre SQL里的多语句、注释与常见写法

pre SQL输入框不是只能写一行,它可以写多条SQL语句,用分号分隔。常见做法是把存储过程调用和会话内变量设置放在一起。比如:

-- 先设置会话参数,再调用存储过程 SET @batch_id = 20240501; CALL SP_ARCHIVE_DATA(@batch_id);

这里SET和CALL按顺序执行。要注意的是,pre SQL文本不是预编译脚本,Informatica不会替你处理变量作用域,它只是把整段文本按分号拆开逐条发给数据库。所以你在pre SQL里写的注释和格式,数据库端执行时都会原样接收。还有一点,pre SQL里如果写了一条返回结果集的SELECT,某些数据库中会导致后续语句被跳过,这个我在排查时遇到过。尽量让pre SQL以存储过程的DML/DDL调用为主,不要返回游标结果。

3. 从建Mapping到跑通:pre SQL调用存储过程的完整落地记录

这一章不做原理铺垫,直接按操作顺序走。我这里以最常见的交互式客户端操作为例,命令行批量提交的情况放在后续讨论。

3.1 新建Mapping,让目标表先就位

在Repository导航器里右键选择New Mapping,命名建议带上业务前缀,比如M_REFRESH_SUMMARY。新建之后,Mapping设计区是空的,需要先把源表和目标表导进来。这里有一个很容易忽略的前提:pre SQL执行的是数据库端操作,目标表必须真实存在于数据库里,并且当前连接账号具备该表的DML权限。如果目标表只是Mapping里手工建的一个虚拟目标,pre SQL不会生效,因为数据库里根本没有对应对象。

做法是:在Mapping菜单里选择Import from Database,把这两个表导入。导入后,Mapping里自然会有对应的表实例,这时候再去配置它的属性。我习惯把目标表放在设计区右侧,源表放在左侧,这样属性对话框打开时,目标表一眼能认出来,不容易把pre SQL配到源表上。

3.2 右键目标表 -> Edit,打开属性选项卡

在Mapping设计区,右键点击目标表实例,选择Edit,弹出的是目标表属性编辑对话框。接着切换到属性选项卡,这个选项卡在不同版本里可能叫Properties、属性或表属性,位置一般都在常规选项旁边。切换过去之后,能看到一个叫Pre SQL的输入框,有的版本写作Pre-session SQL,旁边可能还有一个Post SQL输入框。

这个Pre SQL输入框是自由文本,可以写多条SQL语句,多条之间用分号分隔。需要注意的是,它执行的是数据库端脚本,不是Informatica自己的转换表达式,别往里面塞Mapping函数。我在小版本升级时发现过字段名变化,但核心语义一直没变:加载前执行。如果你打开对话框找不到Pre SQL,先把选项卡挨个看一遍,通常在与SQL、Scripting相关的页签里。还有一类版本把pre SQL缩成一个小图标,要点击后才展开输入区,别忽略。

3.3 在Pre SQL字段写入调用存储过程的脚本

写入格式并不复杂,核心就是一条调用语句。以无参存储过程为例:

-- 调用一个无参存储过程 CALL SP_CLEAN_DATA();

如果存储过程需要入参,直接把参数跟在过程名后面的括号里:

-- 调用带日期参数的存储过程,字符串参数记得加单引号 CALL SP_ARCHIVE_DATA('2024-05-01');

注意,这里用的是CALL关键字,主流商业数据库基本都支持。个别数据库也支持EXEC,但CALL可移植性更好。pre SQL是字符串替换机制,你写什么,Informatica就把它原样交给数据库连接执行。所以分号、引号、注释的写法都要符合数据库端的SQL规范。写完脚本之后,点OK保存Mapping。

参数说明:CALL和EXEC的区别在于,CALL是SQL标准语法,EXEC是某些数据库的扩展调用方式。在pre SQL里统一用CALL,换数据库时改动最小。带参调用时,字符串日期需要加单引号,否则会被解析成算术表达式。

3.4 保存并运行:Session级配置不能少

Mapping保存后,还得建一个Session来执行它,否则Mapping只是一张静态的设计图。在Workflow Manager里新建Session,关联到刚才保存的Mapping,配置源连接和目标连接,确保目标连接指向的数据库账号能够执行存储过程。然后启动Workflow或直接启动Session。

运行后想确认pre SQL是不是真的执行了,有两个办法。第一,翻开Session Log,搜CALL关键字,能看到执行的SQL记录;第二,去数据库端查会话ID或者最新执行日志,大部分数据库都支持查询当前活动会话。如果Session Log里没有CALL记录,那就是pre SQL没有取到,或者被配到了源表属性里,回到3.2重新检查。

还有一个小细节:Session配置里有一个Treat source rows as character data之类的选项,一般不要动。真正影响pre SQL的是Target Connection的连接串和事务模式。连接串连错库,pre SQL写到另一个环境,问题非常隐蔽,检查日志时要把数据库实例也核对一遍。

3.5 用数据库日志反查pre SQL是否发出去

如果Session Log里没有CALL,或者你怀疑pre SQL被跳过,最直接的办法是在数据库端开启SQL Trace或会话级监控,然后重新跑一次Session。正常情况能看到pre SQL在目标表写入之前发起。看不到,就说明Informatica没有把这段脚本发送给数据库。这时候优先检查目标表实例是否真的是Mapping里的写入目标,其次检查属性里是不是存在两个pre SQL字段。版本不同的客户端可能把pre SQL放在“数据对象”而不是“目标表”下,这些都是我遇到过的界面坑。

排查这一步的重要性在于,它能把问题分成两类:一类是配置没生效,一类是数据库执行失败。前者查Informatica端,后者查数据库端。分清楚之后,排障速度会快很多。

4. 变量传参与事务处理:把硬编码调用改成可变调度

固定日期、固定参数的pre SQL只适合一次性手工运行。生产环境里的调度任务,日期参数每天都要变,这就得把pre SQL里的硬编码替换成变量。

4.1 用Mapping参数替换硬编码入参

Informatica里做参数替换,常规做法是在Mapping里定义一个Mapping Parameter或Mapping Variable,然后在pre SQL的SQL文本里引用它。比如定义参数$$RUN_DATE,pre SQL里写:

CALL SP_ARCHIVE_DATA($$RUN_DATE);

这里有个容易翻车的点:pre SQL是纯字符串替换,$$RUN_DATE替换进去之后,到底带不带引号,完全取决于参数本身的值。如果参数在参数文件里定义成RUN_DATE = '2024-05-01',替换后SQL就是CALL SP_ARCHIVE_DATA('2024-05-01'),合法。如果你在参数文件里定义成2024-05-01,不带引号,替换后就变成CALL SP_ARCHIVE_DATA(2024-05-01),数据库会把2024-05-01当成两个整数相减,轻则数据错,重则报错。

所以传给字符串参数时,我习惯在参数文件里把引号一起写好,或者只在pre SQL里拼接单引号。参数说明:Mapping参数以$$开头,区分大小写。在Session的属性设置里,可以给参数赋一个静态值,也可以引用Workflow变量。如果是每日批处理,通常把日期变量从Session的$SYSTEM_DATE拿,赋值给$$RUN_DATE。

4.2 存储过程的返回值怎么处理

存储过程执行完,返回值未必能被Informatica直接看到。更常见的是用数据库异常来传递失败状态:存储过程中一旦发现参数不合法、处理行数为0等业务异常,直接抛出数据库异常,让pre SQL阶段报错,从而把整个Session置为失败。这是我会主动用的一种做法。

-- 存储过程内部示例:失败时主动报错 IF l_cnt = 0 THEN RAISE_APPLICATION_ERROR(-20001, 'no data found for the given date'); END IF;

这样配置之后,一旦调用失败,Session Log里会带上这个异常码和错误信息,排查起来比静默返回一个-1要好得多。如果你非要拿存储过程的返回值来控制Mapping分支,那需要额外的游标和参数映射,成本高,不推荐。真正的业务分支应该放在Workflow层,根据Session状态决定是否调用下游。

4.3 Pre SQL与Post SQL组合:加载前后各管一段

以我最近做过的一个数据归档任务为例。目标表先要被存储过程清空,然后Mapping把源表里的当月明细写进来,写完之后再调用另一个存储过程刷新汇总表。三段逻辑分别落在三个位置:

-- Pre SQL:加载前清空并准备归档段 CALL SP_PREPARE_ARCHIVE('2024-05-01');
-- Post SQL:加载后刷新汇总 CALL SP_REFRESH_SUMMARY('2024-05-01');

Pre SQL和Post SQL中间夹着的,就是Mapping本身的写入动作。这种组合在报表生成、日结汇总场景里很常见。顺序上有一点要注意:不要把必须在加载后执行的逻辑放到pre SQL里,否则读到的还是旧数据。反过来,把清理动作放到post SQL里,目标表就可能出现重复数据。

我给这类任务的Mapping定了条规矩:pre SQL只做“准备”和“清空”,post SQL只做“汇总”和“通知”,Mapping只做“明细加载”。三件事各管一段,出了问题看日志时,能很快定位是哪一段。

4.4 事务提交问题提前盯一眼

pre SQL调用的存储过程,和Mapping后续的目标表写入,不一定处在同一事务里。这取决于Informatica连接配置和数据库驱动的自动提交行为。为了不让存储过程执行了一半被回滚,我一般会在存储过程内部显式处理提交,或者在数据库驱动配置里关掉自动提交转用手动提交。这个坑在下一章还会细说。

实际调试时,我会做一个小实验:写一个存储过程只做INSERT,执行完立即在数据库查询这条数据在不在。如果不在,说明事务被回滚或没有提交。然后回到存储过程里加COMMIT,再重复实验。这个小实验能快速判断问题出在事务还是SQL。

4.5 参数文件与Workflow调度联动

生产环境里,参数值很少手工填,更多是来自Workflow变量或参数文件。典型参数文件内容如下:

[MappingVariables] RUN_DATE=$SYSTEM_DATE BATCH_ID=1001

然后把参数文件路径配到Session的属性里。运行Workflow时,$SYSTEM_DATE会被系统替换成当天日期,再传递给pre SQL。这样做的好处是调度器不需要改Mapping,只要在参数文件里调整BATCH_ID,就能控制存储过程的入参。还要注意参数文件的编码,Windows下用记事本另存为UTF-8或系统默认编码,否则中文注释会报错。

5. 避坑与排查:调用存储过程最常见的5个翻车现场

这一章,我把这些年实际踩过的坑整理成“现象→原因→解决”的结构,每条都能直接对号入座。

5.1 现象:pre SQL执行了,但目标表数据没变化

有次我配好CALL语句后,Session状态是成功,进数据库一看,目标表还是空的,数据一条没多。原因很丢人:存储过程内部执行了INSERT,但没COMMIT,pre SQL返回正常,Informatica会话接着做后续操作,可事务最终被回滚了。数据库连接认为整个事务失败或者没有提交指令,数据就没有落盘。

解决办法是在存储过程内部按业务节点显式提交。如果你不想改存储过程,可以检查Informatica目标连接的自动提交配置,但更稳妥的做法还是在过程内处理提交,因为存储过程往往也会被别处复用。从那以后,我写存储过程给ETL用时,都会在结尾加COMMIT,宁多不少。

5.2 现象:带参数的pre SQL跑不过,提示字符串格式错误

我在4.1里提到过引号问题,实际翻车现场长这样:参数文件里写RUN_DATE = 2024-05-01,pre SQL里写CALL SP_ARCHIVE_DATA($$RUN_DATE);。替换后,数据库看到的是SP_ARCHIVE_DATA(2024-05-01),报错说标识符无效。原因是日期没加引号,被解析成表达式。

解决方式要么在参数文件里带上引号,要么在pre SQL里写成CALL SP_ARCHIVE_DATA('$$RUN_DATE');。第二种写法更直观,参数替换后变成'2024-05-01',稳定得多。这个坑在月切日期、参数带小数点时尤其容易出现,养成“先看替换后的SQL”的习惯能省不少时间。

5.3 现象:会话日志里搜不到任何CALL记录

这个现象一般指向配置位置不对。pre SQL字段只有在目标表被Mapping真正使用时才会生效,很多新手把pre SQL填在了源表属性里,或者填好后没有点Apply,或者同一个Mapping里有多个目标表,填错了表。

解决办法:回到Mapping,右键目标表实例检查属性;如果目标表是从数据库导入的实际表对象,确认Mapping里只有这一个目标表。再不行,查看Session属性里的Connection Environment,确认连到的数据库正是存储过程所在的实例。会话日志搜不到CALL,往往是配置没被Mapping引用,而不是数据库端的问题。

5.4 现象:存储过程内部报错,但Informatica会话显示成功

这是最坑的一种,因为数据库驱动器可能把存储过程中的错误给吞了。比如存储过程里用了异常捕获,把错误写进了日志表,没有继续抛出,那么pre SQL在数据库层面是执行成功的,Informatica自然认为会话成功。

解决方法是先改存储过程,让它在关键校验失败时主动RAISE异常,而不是catch住了就完事;然后在Mapping的pre SQL阶段保留CALL语句,让它成为唯一入口。这样只要过程内部有异常,会话就会失败,日志里也能看到异常码。记住一条原则:对ETL来说,静默吞错比直接报错危险得多。

5.5 现象:传Mapping变量进去,参数值一直是空

Session运行时,$$RUN_DATE没有从Workflow变量传进去,导致pre SQL拼接出一个CALL SP_ARCHIVE_DATA(),缺参直接报错。原因通常是参数作用域不一致:Mapping里的参数和Workflow里的变量同名,但中间没有做赋值映射。

解决方式是在Session的任务属性里,把Workflow变量或参数文件里的值显式赋给Mapping参数。具体路径是:编辑Session,在Mapping Variables选项卡里,给RUN_DATE赋上引用值或参数文件路径。检查这一项,比我之前一个个看日志快得多。这个坑在多个Workflow共用一个Session时尤其常见,参数文件写得不严谨,变量就会静默落空。

6. 验证与进阶:三种方法确认存储过程真的被调用了

配置完成不代表万事大吉,我每次上线前总会做三件事确认pre SQL真正生效。

第一,看数据前后变化。选一张小的目标表,跑一次Session,在跑之前和执行后分别查询目标表的行数。如果存储过程是删除或插入数据,行数会明显变化,这一步最直接。

-- 跑Session前查一次 SELECT COUNT(*) FROM TARGET_TABLE; -- 跑完再查一次 SELECT COUNT(*) FROM TARGET_TABLE;

第二,看Session Log里的SQL记录。Informatica会话日志会打印pre SQL的具体语句,哪怕参数值都能看到。要养成跑完看一眼日志的习惯,特别是首次配置的Session,确认日志里的CALL语句不是你想象中的那样。

第三,去数据库端打开SQL监控。这个可选,但在排障时特别好用。开启数据库会话级监控后,能看到pre SQL发起的时间、执行的存储过程名称,以及内部每一步的耗时。有些数据库需要额外权限,没有权限的话,就直接在存储过程里写一张日志表,记录每次调用的入参和执行时间。这也是我比较看重的做法,因为日志表等于给存储过程装了一个黑匣子。

从那以后,我每次把存储过程写进pre SQL之前,都会先用数据库账号手工执行一遍CALL,确认这个账号能跑通、能提交,然后才回到Informatica里配置。有一次生产任务凌晨三点失败,排查了两小时,最后发现就是存储过程里少了COMMIT。那次教训让我把“先手工执行”变成了固定动作,省下的时间够改好几个Mapping。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询