The Oracle RMS Organizational Hierarchy
The Merchandise Hierarchy tells RMS what you sell. The Organizational Hierarchy tells it where you sell it. Mastering both is essential — every inventory transaction, purchase order, and stock query in RMS ties a product to a location.
What is the Organizational Hierarchy?
In Oracle RMS, every product that exists in the system must be tied to a location before it can be bought, sold, transferred, or counted. The Organizational Hierarchy is the structure that defines all those locations — from the broadest grouping (Chain) down to the individual Store, plus the separate concept of Warehouses.
Unlike the Merchandise Hierarchy — which classifies products — the Organizational Hierarchy classifies where business happens. The two hierarchies intersect at the item-location level: when an item is ranged to a store or warehouse, a record is created linking the item's merchandise hierarchy position to a location in the organizational hierarchy.
The ITEM_LOC table is where both hierarchies meet. It holds one row
per item-location combination, binding the item's DEPT/CLASS
/SUBCLASS (merchandise hierarchy) to a LOC and
LOC_TYPE (organizational hierarchy). Everything downstream — stock on
hand, cost, replenishment — flows from this intersection.
The Oracle RMS Organizational Hierarchy has two distinct tracks:
The Store Track follows a five-level chain: Chain → Area → Region → District → Store. This represents your physical retail footprint — every store belongs to a District, which rolls up through management levels to the top.
The Warehouse Track sits alongside the store hierarchy. Warehouses are not part of the Chain-to-Store chain — they have their own table (WH) and their own type system (Physical, Virtual, Finisher). But in day-to-day RMS operations, stores and warehouses are treated identically as locations using the same LOC + LOC_TYPE pattern throughout the schema.
The Store Hierarchy — Chain to Store
The store side of the Organizational Hierarchy is a strict five-level parent-child chain. Every store must belong to a District. Every District belongs to a Region. Every Region to an Area. Every Area to a Chain. Skipping a level is not possible — the database enforces this via foreign key constraints.
A Chain in Oracle RMS represents a grouping of stores that share the same retail format or brand identity. A multi-format retailer might have separate Chains for its flagship stores, its outlet centres, and its franchise network. Each Chain can have its own currency, though most single-country retailers operate with a single currency across all chains.
| Column | Type | Description |
|---|---|---|
CHAIN_NOPK | NUMBER(4) | Unique chain identifier |
CHAIN_NAME | VARCHAR2(120) | Chain name |
CURRENCY_CODE | VARCHAR2(3) | Operating currency for this chain |
Areas subdivide a Chain into broad geographic or operational zones. For an Indian retailer, Areas might map to major zones — North, South, East, West — or to major metros like Delhi NCR, Mumbai, Bengaluru. The Area level is typically where senior regional leadership is aligned.
| Column | Type | Description |
|---|---|---|
AREA_NOPK | NUMBER(4) | Unique area identifier |
AREA_NAME | VARCHAR2(120) | Area name |
CHAIN_NOFK | NUMBER(4) | Parent chain (FK → CHAIN) |
Regions sit beneath Areas and group Districts together. In RMS reporting, Region is one of the most commonly used rollup points for operational dashboards — regional managers can see aggregated performance across their Districts and Stores at this level without going all the way to Area or Chain.
| Column | Type | Description |
|---|---|---|
REGION_NOPK | NUMBER(4) | Unique region identifier |
REGION_NAME | VARCHAR2(120) | Region name |
AREA_NOFK | NUMBER(4) | Parent area (FK → AREA) |
The District is the direct parent of the Store in the hierarchy. District managers in retail typically own profit-and-loss responsibility for all the stores in their District. In RMS, store operations, inventory moves, and replenishment can all be administered at the District level before cascading down to individual stores.
| Column | Type | Description |
|---|---|---|
DISTRICT_NOPK | NUMBER(4) | Unique district identifier |
DISTRICT_NAME | VARCHAR2(120) | District name |
REGION_NOFK | NUMBER(4) | Parent region (FK → REGION) |
The Store is the leaf node of the store hierarchy — the physical location where customers buy products. The STORE table is one of the most referenced tables in all of Oracle RMS. It contains the configuration for every operational aspect of the store: its default warehouse for replenishment, its VAT region, its transfer zone, its channel type, and its current status.
The primary key of the STORE table is simply STORE — a number. When this value appears as a location in other RMS tables, it always comes with a LOC_TYPE of 'S' to distinguish it from warehouse locations.
| Column | Type | Description |
|---|---|---|
STOREPK | NUMBER(10) | Unique store number — also used as LOC in ITEM_LOC, ORDLOC, etc. |
STORE_NAME | VARCHAR2(150) | Store display name |
DISTRICT_NOFK | NUMBER(4) | Parent district (FK → DISTRICT) |
STORE_TYPE | VARCHAR2(1) | C = Company owned, F = Franchise, W = Warehouse (used as store) |
CHANNEL | VARCHAR2(6) | Sales channel — STORE, WEB, CATALOG, etc. |
DEFAULT_WH | NUMBER(10) | FK → WH. The default warehouse that replenishes this store |
VAT_REGION | NUMBER(4) | VAT region for this store — drives tax calculation |
TRANSFER_ZONE | NUMBER(4) | Determines which stores this store can transfer stock to/from |
CURRENCY_CODE | VARCHAR2(3) | Operating currency for this store |
STATUS | VARCHAR2(1) | A = Active, I = Inactive, C = Closed |
Warehouses — Physical, Virtual and Finisher
Warehouses in Oracle RMS are all stored in a single table — WH. The WH_TYPE column discriminates between the three fundamental warehouse types. Understanding the difference between a Physical and a Virtual warehouse is essential for any developer working on inventory, ordering, or replenishment logic.
Unlike the store hierarchy which spans five tables (CHAIN → AREA → REGION → DISTRICT → STORE), all warehouse types live in the single WH table. The relationship between Physical and Virtual warehouses is expressed within the same table — a Virtual WH's DEFAULT_WH column points to its parent Physical WH.
When a warehouse appears as a location in RMS tables like ITEM_LOC or ORDLOC, the WH primary key value is used as the LOC, and the LOC_TYPE is set to 'W'.
| Column | Type | Description |
|---|---|---|
WHPK | NUMBER(10) | Unique warehouse number. Used as LOC in ITEM_LOC, ORDLOC, etc. |
WH_NAME | VARCHAR2(150) | Warehouse name |
WH_TYPE | VARCHAR2(2) | PA = Physical · VA = Virtual · EX = External Finisher |
DEFAULT_WH | NUMBER(10) | For virtual WHs: FK → parent physical WH. NULL for physical WHs. |
CURRENCY_CODE | VARCHAR2(3) | Operating currency of this warehouse |
PROTECTED_IND | VARCHAR2(1) | Y = protected warehouse (inventory cannot be moved freely) |
FINISHER_IND | VARCHAR2(1) | Y = this warehouse performs finishing work on items |
VAT_REGION | NUMBER(4) | VAT region for this warehouse |
Purchase Orders are received into Physical Warehouses. A Virtual Warehouse cannot directly receive a PO — stock is received at the Physical WH level and then logically allocated to Virtual WHs. Trying to create a PO to a Virtual WH will fail validation.
The LOC + LOC_TYPE Pattern — Most Important Concept
This is the single most important architectural pattern in Oracle RMS for developers to understand. Throughout the entire RMS schema, whenever a table needs to store a reference to a location — whether a store or a warehouse — it does so using two columns together: LOC (the location number) and LOC_TYPE (a code indicating what kind of location it is).
This pattern appears on dozens of tables — ITEM_LOC, ITEM_LOC_SOH, ORDLOC, TSFHEAD, STKLEDGR, and many more. Every time you query these tables, you must filter by both LOC and LOC_TYPE together, or you risk pulling records from the wrong location type.
The valid LOC_TYPE values you will encounter are:
| Column | Type | Description |
|---|---|---|
'S' | STORE | Store |
'W' | WH | Warehouse |
'E' | WH (WH_TYPE='EX') | External Finisher |
'A' | AREA | Area |
'R' | REGION | Region |
'D' | DISTRICT | District |
The pattern to always follow: WHERE ils.loc = :v_loc AND ils.loc_type = 'S'
for stores, AND ils.loc_type = 'W' for warehouses. Omitting the LOC_TYPE
filter is the most common source of incorrect results in custom RMS queries.
RC:OMS was built with the same location-aware inventory thinking as Oracle RMS — every stock movement is a double-entry ledger transaction, tracked by location. Amazon FBA, Flipkart, Shopify, WooCommerce, and your own Storefront — all managed from a single source of truth.
Explore RC:OMS →Stores vs Warehouses — Key Differences in RMS
From a database perspective, stores and warehouses are both just "locations" in RMS. But they behave very differently in business logic.
| Dimension | StoresLOC_TYPE = 'S' | WarehousesLOC_TYPE = 'W' |
|---|---|---|
| Hierarchy | CHAIN → AREA → REGION → DISTRICT → STORE | Standalone — not part of the store chain |
| Replenishment | Has DEFAULT_WH — receives stock from a warehouse | Physical WHs receive Purchase Orders directly |
| Purchase Orders | Cannot receive POs directly | Physical WHs receive POs; Virtual WHs cannot |
| Stock on Hand | SOH = sellable floor stock | SOH = bulk / storage stock |
| Sales | Sales transactions reduce SOH (via ReSA/POS) | No direct sales — dispatches to stores via Transfers |
| Status | A (Active) / I (Inactive) / C (Closed) | |
| Nesting | One store per row | Virtual WHs nest under Physical WHs via DEFAULT_WH |
Key Database Tables — Quick Reference
Practical SQL Examples
1. Full store hierarchy path — store to chain
-- Full store hierarchy rollup for a given store
SELECT s.store,
s.store_name,
s.store_type,
s.status,
d.district_name,
r.region_name,
a.area_name,
c.chain_name,
s.default_wh,
w.wh_name default_wh_name
FROM store s
JOIN district d ON d.district_no = s.district_no
JOIN region r ON r.region_no = d.region_no
JOIN area a ON a.area_no = r.area_no
JOIN chain c ON c.chain_no = a.chain_no
LEFT JOIN wh w ON w.wh = s.default_wh
WHERE s.store = :v_store;2. Stock on hand for an item — across all stores and warehouses
-- Item SOH across all locations (stores + warehouses combined)
-- Uses UNION to join both location types with their names
SELECT 'STORE' loc_type_desc,
s.store loc_no,
s.store_name loc_name,
ils.stock_on_hand,
ils.av_cost,
ils.unit_retail
FROM item_loc_soh ils
JOIN store s ON s.store = ils.loc
WHERE ils.item = :v_item
AND ils.loc_type = 'S'
AND ils.stock_on_hand > 0
UNION ALL
SELECT 'WAREHOUSE' loc_type_desc,
w.wh loc_no,
w.wh_name loc_name,
ils.stock_on_hand,
ils.av_cost,
ils.unit_retail
FROM item_loc_soh ils
JOIN wh w ON w.wh = ils.loc
WHERE ils.item = :v_item
AND ils.loc_type = 'W'
AND ils.stock_on_hand > 0
ORDER BY loc_type_desc, loc_no;
3. All active stores with their default warehouses in a region
-- Operational report: active stores in a region with warehouse info
SELECT s.store,
s.store_name,
s.store_type,
d.district_name,
w.wh default_wh_no,
w.wh_name default_wh_name,
w.wh_type
FROM store s
JOIN district d ON d.district_no = s.district_no
JOIN region r ON r.region_no = d.region_no
LEFT JOIN wh w ON w.wh = s.default_wh
WHERE r.region_no = :v_region
AND s.status = 'A'
ORDER BY d.district_name, s.store_name;4. PL/SQL — Validate a location exists (any type)
-- Function to validate a LOC + LOC_TYPE combination
-- Used in integration staging validation before inserting to RMS
FUNCTION loc_exists (
p_loc IN item_loc.loc%TYPE,
p_loc_type IN item_loc.loc_type%TYPE
) RETURN BOOLEAN IS
l_count PLS_INTEGER := 0;
BEGIN
IF p_loc_type = 'S' THEN
SELECT COUNT(1) INTO l_count
FROM store
WHERE store = p_loc
AND status = 'A';
ELSIF p_loc_type = 'W' THEN
SELECT COUNT(1) INTO l_count
FROM wh
WHERE wh = p_loc;
END IF;
RETURN (l_count > 0);
EXCEPTION
WHEN OTHERS THEN
RETURN FALSE;
END loc_exists;
Common Gotchas for Developers
- !
Querying ITEM_LOC without a LOC_TYPE filter. Store 101 and Warehouse 101 are completely different locations with the same LOC value. Filtering by only
LOC = 101will return rows for both. Always includeAND LOC_TYPE = 'S'or'W'explicitly. - !
Treating Virtual Warehouses like Physical Warehouses in PO logic.
Purchase Orders are received into Physical Warehouses. A Virtual Warehouse cannot directly receive a PO — stock is received at the Physical WH level and then logically allocated to Virtual WHs. Trying to create a PO to a Virtual WH will fail validation.
- !
Forgetting that STORE and WH number ranges can overlap. There is no technical separation in RMS preventing Store 5000 and Warehouse 5000 from coexisting. The LOC_TYPE is the only discriminator. Integration scripts that strip LOC_TYPE and try to look up just by number will fail silently or return wrong data.
- !
Assuming DEFAULT_WH on STORE is always set. In some RMS configurations, stores may not have a DEFAULT_WH assigned — especially during initial data migration or for online-only stores. Always LEFT JOIN on WH when reading DEFAULT_WH, or validate for NULL before using it in batch logic.
- !
Missing the difference between Store STATUS values. A store with
STATUS = 'I'(Inactive) still exists in the hierarchy and may still have stock on hand.STATUS = 'C'(Closed) means the store has completed closure. Logic that only checks forSTATUS = 'A'will miss Inactive stores that still need inventory management. - !
Using LOC_TYPE = 'A' (Area) in item_loc context. LOC_TYPE values like 'A', 'R', 'D' (Area, Region, District) are used in some RMS contexts for aggregated pricing and promotion assignment — but they are not valid in ITEM_LOC or ITEM_LOC_SOH. Those tables only accept 'S', 'W', or 'E'.
Key Takeaways
- ✓The RMS Organizational Hierarchy has two tracks: Store (CHAIN → AREA → REGION → DISTRICT → STORE) and Warehouse (WH table with WH_TYPE)
- ✓All three warehouse types — Physical (PA), Virtual (VA), and Finisher (EX) — live in the single WH table. Virtual WHs reference their parent via DEFAULT_WH.
- ✓The LOC + LOC_TYPE pattern is the most important architectural concept — stores use LOC_TYPE = 'S', warehouses use 'W'. Always filter by both columns together.
- ✓ITEM_LOC and ITEM_LOC_SOH are where the Merchandise and Organizational hierarchies intersect. One row per item per location.
- ✓Store SOH = sellable floor stock. Warehouse SOH = bulk/storage stock. Both live in ITEM_LOC_SOH but with different LOC_TYPE values.
- ✓STORE.DEFAULT_WH links each store to its replenishment source — this is critical for replenishment batch logic.
