Understanding OData Deep Insert in SAP: A Practical Overview
What is OData Deep Insert?
OData Deep Insert is used when we need to create a main record along with its related records in one go. For example, if we're creating a sales order and want to include multiple items in that order, instead of calling the service multiple times (once for the header and once for each item), we can just send everything together in one request. This helps reduce the number of API calls and keeps things more efficient.
Where Is It Used?
Let’s say we’re placing a new sales order:
- The header contains information like the customer, order date, and total value.
- The items include details such as product, quantity, and price.
With Deep Insert, we can send both the header and item data together in one single payload. This is useful in real-time integrations or web applications where performance and fewer network calls matter.
How to Implement It in SAP OData
- Define the Entity Model in SEGW
We’ll need to create two entity types:
- SalesOrder: Represents the header.
- SalesOrderItem: Represents the line items.
Then create an association between them, showing that a sales order can have multiple items.
- Redefine CREATE_DEEP_ENTITY in DPC_EXT Class
This is where we will handle the payload in the backend.
METHOD create_deep_entity.
DATA: ls_header_input TYPE zcl_zdeep_demo_mpc=>ts_salesorder,
lt_item_input TYPE STANDARD TABLE OF zcl_zdeep_demo_mpc=>ts_salesorderitem,
ls_item_input TYPE zcl_zdeep_demo_mpc=>ts_salesorderitem,
ls_order_header TYPE bapisdhd1,
lt_items TYPE STANDARD TABLE OF bapisditm,
ls_item TYPE bapisditm,
lt_partners TYPE STANDARD TABLE OF bapiparnr,
ls_partner TYPE bapiparnr,
lt_return TYPE STANDARD TABLE OF bapiret2,
ls_return TYPE bapiret2,
lv_salesdoc TYPE vbak-vbeln.
" Extract header & item data from payload
ls_header_input = is_deep_entity.
lt_item_input = is_deep_entity-toitems.
" Map header to BAPI structure
ls_order_header-doc_type="OR". " Order type
ls_order_header-sales_org = '1000'.
ls_order_header-distr_chan = '10'.
ls_order_header-division = '00'.
" Add Sold-to Party (AG)
CLEAR ls_partner.
ls_partner-partn_role="AG".
ls_partner-partn_numb = ls_header_input-customer.
APPEND ls_partner TO lt_partners.
" Optionally, Ship-to Party (WE) same as Sold-to
CLEAR ls_partner.
ls_partner-partn_role="WE".
ls_partner-partn_numb = ls_header_input-customer.
APPEND ls_partner TO lt_partners.
" Map item data
LOOP AT lt_item_input INTO ls_item_input.
CLEAR ls_item.
ls_item-itm_number = ls_item_input-itemid.
ls_item-material = ls_item_input-material.
ls_item-target_qty = ls_item_input-quantity.
APPEND ls_item TO lt_items.
ENDLOOP.
" Call BAPI
CALL FUNCTION 'BAPI_SALESORDER_CREATEFROMDAT2'
EXPORTING
order_header_in = ls_order_header
IMPORTING
salesdocument = lv_salesdoc
TABLES
return = lt_return
order_items_in = lt_items
order_partners = lt_partners.
" Check for any errors (E/A/X)
LOOP AT lt_return INTO ls_return WHERE type="E" OR
type="A" OR
type="X".
RAISE EXCEPTION TYPE /iwbep/cx_mgw_busi_exception
EXPORTING
textid = /iwbep/cx_mgw_busi_exception=>business_error
message = ls_return-message.
ENDLOOP.
" Commit work
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
EXPORTING
wait = abap_true.
" Fill deep entity response
er_deep_entity-salesorderid = lv_salesdoc.
er_deep_entity-customer = ls_header_input-customer.
er_deep_entity-orderdate = ls_header_input-orderdate.
ENDMETHOD.
Make sure both header and items are saved in the same transaction to maintain consistency.
- Testing
We can test this service using Postman or /IWFND/GW_CLIENT in SAP. A sample payload might look like:
{
"Customer": "1000001",
"OrderDate": "2025-08-05T00:00:00",
"ToItems":[{ "ItemID": "10",
"Material": "MATERIAL001",
"Quantity": 5 },
{ "ItemID": "20",
"Material": "MATERIAL002",
"Quantity": 3 } ]
}
Common Issues and Solutions
- Items not saving?
Check if the association and navigation are correctly defined. - CREATE_DEEP_ENTITY not triggered?
Make sure you've redefined the method and mapped the navigation properly in SEGW. - Data inconsistency after commit?
Handle errors correctly and roll back changes if needed.
Real-World Example
A retail company has a frontend ordering app. When a customer checks out, the app sends the order header and all items in one payload using Deep Insert. The backend saves everything in one shot, ensuring performance and data consistency.
In Summary
Deep Insert in OData is extremely helpful when dealing with parent-child relationships like orders and order items. It reduces complexity and improves performance by eliminating multiple round-trips to the server. When implemented correctly, it can streamline our data entry scenarios and backend integration.



