The relationship between sc_request and sc_req_item is straightforward, but catalog variables live in a third table most developers miss: sc_item_option_mtom. This many-to-many relationship stores the actual variable values that users submitted, and you need to join through sc_item_option to get variable metadata. The pattern above handles both the RITM enumeration and variable extraction in a single pass, avoiding the N+1 query trap that kills performance when you have requests with dozens of items.
When to use this pattern
- Processing approval workflows that need to act on individual RITMs within a request
- Business rules on
sc_requestthat need to validate or modify child items before completion - Scheduled jobs that process batches of requests and need RITM-level detail for reporting or integration
- Fix scripts that need to bulk-update RITMs based on parent request criteria
When NOT to use this pattern
- Client-side scripts — use
GlideAjaxto call a Script Include that implements this pattern - When you only need RITM counts or aggregates — use
GlideAggregatewithaddAggregate('COUNT') - Inside loops over other GlideRecord results — you'll create a query storm that times out on large datasets
- Processing requests with 50+ RITMs in synchronous business rules — use events or scheduled processing instead
Key behaviors and gotchas
- RITM
statevalues are integers: 1=Open, 2=Work in Progress, 3=Closed Complete, 4=Closed Incomplete, 7=Closed Skipped - Catalog variables require joining through
sc_item_option_mtom— they're not fields onsc_req_item - Variable values are always strings, even for numeric and boolean catalog variables
- RITMs inherit ACLs from their catalog items — not all RITMs in a request may be visible to the current user
- Multi-row variable sets create multiple
sc_item_option_mtomrecords per RITM — group byrow_indexif needed - The
requestfield onsc_req_itemis indexed — queries by request are fast even with thousands of RITMs
Never use dot-notation like current.ritems to navigate from request to RITMs — it returns a GlideElement, not a GlideRecord, and you can't iterate or query it. Always query sc_req_item explicitly with the request sys_id.
Enjoying this? Get one deep-dive per week.
Join 1,000+ ServiceNow pros — scripts, GlideRecord patterns, Flow Designer techniques, and career moves. Free.