ORACLE EBS中消息队列fnd_msg_pub、fnd_message在PL/SQL中的应用

本文介绍了Oracle EBS中如何利用FND_MSG Pub进行错误信息的收集和输出。通过设置消息名称、替换消息内容中的变量,可以方便地在PL/SQL包中实现错误提示和日志记录。此外,还展示了如何使用存储过程封装输出错误信息,并在异常处理中应用,确保了系统异常时的错误信息完整记录。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

EBS 中集成的FND_MSG处理很方便的在form中很方便的弹窗、提示消息之外,在写PL/SQL包的时候,也可以方便的进行借用来进行错误信息的收集。并且这个是基于session的,不同于客户化的log日志表。

原理及用法说明

图片1(IBY_UNIQ_ACCOUNT):
实例图片1
图片2(AFDICT- DATABASE STATS):
实例图片2
实例代码:

DECLARE
   x_msg_count NUMBER;
   x_msg_data  VARCHAR2(3000);

   v_msg_index_out NUMBER;
   v_data          VARCHAR2(1000);
BEGIN

   fnd_msg_pub.Initialize;--或者 fnd_message.CLEAR;
   fnd_message.set_name('IBY', 'IBY_UNIQ_ACCOUNT'); --设置消息名称
   fnd_msg_pub.add; --添加到Global Area

   fnd_message.set_name('FND', 'AFDICT- DATABASE STATS'); --设置消息名称
   fnd_message.set_token('UPDATES', 'Steven123'); --设置消息内容中变量的值
   fnd_message.set_token('INSERTS', 'Steven321'); --设置消息内容中变量的值
   fnd_msg_pub.add; --添加到Global Area

   --当x_msg_count 为1时,直接输出x_msg_data,否则需要循环输出
   fnd_msg_pub.count_and_get(p_encoded => fnd_api.g_false, p_count => x_msg_count, p_data => x_msg_data);

   dbms_output.put_line('x_msg_count:' || x_msg_count);
   dbms_output.put_line('x_msg_data:' || x_msg_data);

   FOR k IN 1 .. x_msg_count
   LOOP
      fnd_msg_pub.get(p_msg_index     => k,
                      p_encoded       => fnd_api.g_false,
                      p_data          => v_data,
                      p_msg_index_out => v_msg_index_out);
      dbms_output.put_line('(' || v_msg_index_out || ')->' || v_data);
   END LOOP;
   fnd_msg_pub.delete_msg();
END;

输出信息:

x_msg_count:2
x_msg_data:
(1)->外部银行帐户已存在
(2)->已更新 Steven123 信息,并已插入 Steven321 信息。

由上面可以看出fnd_message.set_name(APPLICATION => , NAME => ); 这个过程第一个参数是填入应用简称,第2个填入预先定义好的错误消息代码。
fnd_message.set_token(‘UPDATES’, ‘Steven123’) 就是把消息定义中的&XXX 给替换成实际的值。

存储过程二次封装

输出的时候一般用下面这个存储过程输出:

PROCEDURE log_message_list_p IS
    l_msg_index NUMBER;
    l_msg_data  VARCHAR2(2000);
    -------------------------------输出消息队列里面的消息-----------------------
  BEGIN
    IF (fnd_msg_pub.count_msg > 0) THEN
      log_p('Error Message Stack :');
      log_p('----------------------------------------');
      FOR i IN 1 .. fnd_msg_pub.count_msg LOOP
        fnd_msg_pub.get(p_msg_index     => i,
                        p_encoded       => fnd_api.g_false,
                        p_data          => l_msg_data,
                        p_msg_index_out => l_msg_index);
        log_p(l_msg_data);
      END LOOP;
      log_p('format_error_stack:' || chr(10) ||
                dbms_utility.format_error_stack);
      log_p('format_call_stack:' || chr(10) ||
                dbms_utility.format_call_stack);
      log_p('format_error_backtrace:' || chr(10) ||
                dbms_utility.format_error_backtrace);
    END IF;
  EXCEPTION
    WHEN OTHERS THEN
      NULL;
  END log_message_list_p;

在请求中的应用

如果用到EBS请求中的话,还可以这样用:

PROCEDURE main_p(errbuf            OUT VARCHAR2,
                       retcode           OUT VARCHAR2,
                       p_period_num_from IN VARCHAR2,
                       p_period_num_to   IN VARCHAR2) IS
    l_return_status VARCHAR2(30);
    l_msg_data      VARCHAR2(2000);
    l_msg_count     NUMBER;
    ------------------------------调用输出程序------------------
  BEGIN
    retcode := '0';

	--............................
	--业务处理逻辑代码XXXXX
	--调用标准API
	--...........................
EXCEPTION
    WHEN fnd_api.g_exc_error THEN
      log_message_list_p;
      retcode := '1';
      fnd_msg_pub.count_and_get(p_encoded => fnd_api.g_false,
                                p_count   => l_msg_count,
                                p_data    => l_msg_data);
      IF l_msg_count > 1 THEN
        l_msg_data := fnd_msg_pub.get_detail(p_msg_index => fnd_msg_pub.g_first,
                                             p_encoded   => fnd_api.g_false);
      END IF;
      errbuf := l_msg_data;
    WHEN fnd_api.g_exc_unexpected_error THEN
      log_message_list_p;
      retcode := '2';
      fnd_msg_pub.count_and_get(p_encoded => fnd_api.g_false,
                                p_count   => l_msg_count,
                                p_data    => l_msg_data);
      IF l_msg_count > 1 THEN
        l_msg_data := fnd_msg_pub.get_detail(p_msg_index => fnd_msg_pub.g_first,
                                             p_encoded   => fnd_api.g_false);
      END IF;
      errbuf := l_msg_data;
    WHEN OTHERS THEN
      log_p(dbms_utility.format_error_stack ||
                dbms_utility.format_error_backtrace);
      fnd_msg_pub.add_exc_msg(p_pkg_name       => g_pkg_name,
                              p_procedure_name => 'MAIN_P',
                              p_error_text     => substrb(SQLERRM, 1, 240));
      log_message_list_p;
      retcode := '2';
      errbuf  := SQLERRM;
  END main_p;

参考资料

http://blog.itpub.net/25684327/viewspace-694126/
https://imdjkoch.wordpress.com/tag/fnd_message-set_token/
https://docs.oracle.com/cd/E18727_01/doc.121/e12897/T302934T462354.htm

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贤时间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值