【案例总结】幽灵单据——消失的交货单号

这篇文章应该叫做,《ABAPer在SE37测试BAPI时不COMMIT WORK的后果》

注意:本篇文章的解答是AI deepseek回答的,如有侵权, 立即私聊 我,卑微Sesy在线求饶!

目录

背景

解答

一、根本原因分析

二、关键点解读

[三、80000001 和 80000002 的命运](#三、80000001 和 80000002 的命运)

结论

[80000001 和 80000002 在哪里?](#80000001 和 80000002 在哪里?)

如何避免这种情况?

总结

延申

一、创建测试序列的方法

[二、理解 BAPI 的行为](#二、理解 BAPI 的行为)


背景

我在SAP系统SE37中测试BAPI:BAPI_OUTB_DELIVERY_CREATE_SLS创建交货单,创建成功,也返回了交货单号80000001,但是我在后台表SE16N :LIKP和LIPS表中都没有查询到。然后我继续使用BAPI创建了交货单号80000002,也是相同结果。后面我使用测试序列,在SE37调用bapi后,继续调用bapi:bapi_TRANSACTION_COMMIT,创建了交货单号80000003,然后commit后,就能够在LIKP和LIPS表中找到80000003这个交货单号了。但是!80000001和80000002这两个交货单号消失了,在任何一个后台表都找不到,所以该如何找到80000001和80000002这两个单据呢?

解答

这个问题非常典型,涉及到 SAP BAPI 执行的核心机制:数据库提交(COMMIT)。

一、根本原因分析

BAPI_OUTB_DELIVERY_CREATE_SLS 的机制:这个 BAPI 的主要功能是在内存(应用服务器缓冲区) 中构建交货单所需的所有数据(抬头 LIKP、行项目 LIPS、相关表数据等)。

当它执行成功时,它会:在内存中生成完整的交货单结构。分配一个交货单号(如 80000001, 80000002)。将这个号码通过 RETURN 参数或 DELIVERY 参数(取决于 BAPI 具体版本和参数设置)返回给调用者。

二、关键点解读

它本身并不执行数据库的写入(INSERT/UPDATE)操作! 它只是准备好数据。

数据库持久化(写入硬盘)需要显式提交:要使 BAPI 在内存中准备的数据真正保存到数据库表(LIKP, LIPS, VBTK 等)中,必须显式地提交数据库事务。

在第三次测试中,我调用了 BAPI_TRANSACTION_COMMIT。这个 BAPI 的作用就是:将当前 SAP LUW (Logical Unit of Work) 中所有未提交的数据库更改(包括BAPI_OUTB_DELIVERY_CREATE_SLS 创建的交货单数据)真正写入数据库。执行一个数据库 COMMIT WORK 操作。

这就是为什么只能在数据库表中看到 80000003。

三、80000001 和 80000002 的命运

当只调用 BAPI_OUTB_DELIVERY_CREATE_SLS 而没有调用 BAPI_TRANSACTION_COMMIT 时:交货单数据(80000001, 80000002)只存在于应用服务器的内存缓冲区中。它们尚未被写入数据库表(LIKP, LIPS)。当会话(Session)结束、退出事务码(如 SE37)、或者系统执行隐式回滚时(例如超时、程序异常终止),SAP 会自动执行一个 ROLLBACK WORK。ROLLBACK WORK 的作用就是撤销当前 SAP LUW 中所有未提交的数据库更改。

因此,80000001 和 80000002 的数据被丢弃了,它们从未真正写入数据库。

结论

80000001 和 80000002 在哪里?

它们不存在于数据库(LIKP, LIPS 或任何相关表)中。 因为没有提交,数据从未写入硬盘。它们也不存在于任何临时表或缓冲区中(在会话结束后)。 回滚操作清除了所有痕迹。简单地说:80000001 和 80000002 被系统"丢弃"了。它们只是短暂存在于内存中但未被持久化的编号。 它们不是有效的、可用的交货单。

如何避免这种情况?

始终在成功调用创建/更改数据的 BAPI 后提交事务:

在 SE37 测试时,使用BAPI_TRANSACTION_COMMIT。

在 ABAP 程序中调用 BAPI 时,在检查 RETURN 参数没有错误消息 (TYPE 不是 'E' 或 'A') 后,调用 COMMIT WORK 语句。

复制代码
abap代码示例:

CALL FUNCTION 'BAPI_OUTB_DELIVERY_CREATE_SLS'

  EXPORTING

    ...

  IMPORTING

    ...

  TABLES

    ...

    return = lt_return.

" 检查是否有错误

LOOP AT lt_return INTO ls_return WHERE type CA 'EA'.

  EXIT.

ENDLOOP.

IF sy-subrc <> 0. " 没有严重错误

  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'

    EXPORTING

      wait = 'X'. " 等待提交完成

ELSE.

  " 处理错误,通常需要调用 BAPI_TRANSACTION_ROLLBACK

  CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.

ENDIF.

使用测试序列(Test Sequence)功能: 就像第三次测试那样,在 SE37 的测试环境中,可以在调用创建 BAPI 后,紧接着调用 BAPI_TRANSACTION_COMMIT。这是测试这类 BAPI 的标准做法。

总结

80000001 和 80000002 无法找回,因为它们从未被保存到数据库。它们是前两次未提交事务的"幽灵"单据。在 SAP 中,对于创建或修改重要业务数据(如交货单、销售订单、采购订单等)的 BAPI,成功调用 BAPI 并返回成功信息(如单号)只表示数据在内存中准备好了,必须再执行显式的 COMMIT 操作(通过 BAPI_TRANSACTION_COMMIT 或 COMMIT WORK)才能真正写入数据库并生效。 这是 SAP 事务处理机制的核心原则。

延申

一、创建测试序列的方法

在SE37界面,点击功能模块>执行>测试序列

点击测试序列,在弹框中输入函数名称,这里我是测试了BAPI和COMMIT WORK,我的界面如下:

完成后打勾就可以在BAPI调用成功后,进行COMMIT WORK提交了

二、理解 BAPI 的行为

务必查阅 BAPI 的文档(在 SE37 的 Documentation 标签页)。很多创建/更改数据的 BAPI 都需要显式提交。

相关推荐
菜鸟学Python9 分钟前
Python web框架王者 Django 5.0发布:20周年了!
前端·数据库·python·django·sqlite
小云数据库服务专线21 分钟前
GaussDB 查看会话连接数
数据库·gaussdb
墨迹的陌离2 小时前
【Linux】重生之从零开始学习运维之Mysql
linux·运维·服务器·数据库·学习·mysql
BigBigHang3 小时前
【docker】DM8达梦数据库的docker-compose以及一些启动踩坑
数据库·docker·容器
m0_720245013 小时前
QT(四)基本组件
数据库·qt·microsoft
Databend3 小时前
使用 Databend Cloud 归档 OceanBase 数据数据库
数据库
fei飛fei飞4 小时前
数据库事务中的陷阱:脏读、幻读与不可重复读
数据库
FINE!(正在努力!)4 小时前
关于sql面试积累
数据库·sql
看天走路吃雪糕4 小时前
墨者:SQL过滤字符后手工绕过漏洞测试(万能口令)
数据库·sql·sql注入·墨者学院·万能口令
阿里云大数据AI技术5 小时前
【跨国数仓迁移最佳实践3】资源消耗减少50%!解析跨国数仓迁移至MaxCompute背后的性能优化技术
数据库·数据分析·云计算