Oracle Retail20 min readBy Priyanshu Pandey

The Oracle Retail Extension Model: Custom Tables, Flex Attributes & Upgrade-Safe Customization

A comprehensive guide to the Oracle RMS Extension Model. Learn how to create CUST_ extension tables, use flex attributes for custom fields, implement custom PL/SQL hooks, build upgrade-safe integrations via ORDS REST APIs, and avoid the technical debt of base code modifications.

Phase 9 · RMS Development & Customization

How to safely customize Oracle RMS without breaking the upgrade path — because every base modification is a debt you'll pay at upgrade time.

20 min read📅Jun 1, 2026✍️Priyanshu Pandey📚Oracle RMS Series
WHY THIS EXISTS

Why the Extension Model Exists

Every retailer has unique business requirements that Oracle's base RMS product doesn't cover. A fashion retailer needs fabric composition tracking. A grocery retailer needs shelf-life management. An electronics retailer needs warranty period tracking.

The Extension Model provides a structured, upgrade-safe way to add this custom functionality without modifying Oracle's base code.

THE PROBLEM

The Old Way: Base Modifications

Before the Extension Model, retailers customized RMS by directly modifying Oracle's base code:

THE BAD OLD DAYS:

1. ALTER TABLE item_master ADD fabric_type VARCHAR2(50);     ❌
2. Modified base PL/SQL package: ITEM_ATTRIB_SQL             ❌
3. Modified base Oracle Form: fm_item.fmb                    ❌
4. Added custom trigger on ITEM_MASTER: AFTER INSERT          ❌

Each of these modifications created technical debt that accumulated with every Oracle patch and upgrade:

  • Oracle's patch tries to ALTER the same table → conflict
  • Oracle's patch replaces the PL/SQL package → your customizations are overwritten
  • Oracle's patch updates the Form module → merge conflict in binary files
  • Oracle's patch adds a new trigger → trigger execution order conflicts

The result: upgrades that should take 3 months took 18 months. Some retailers were so deeply customized that they could never upgrade — they were permanently stuck on v14.

THE EXTENSION SCHEMA

The Extension Schema Pattern

The Extension Model separates custom code into a dedicated extension schema that Oracle never touches:

┌──────────────────────┐     ┌──────────────────────┐
│   RMS BASE SCHEMA    │     │  EXTENSION SCHEMA    │
│   (Oracle-owned)     │     │  (Retailer-owned)    │
│                      │     │                      │
│  ITEM_MASTER    ◄────FK────│  CUST_ITEM_ATTR      │
│  ORDHEAD        ◄────FK────│  CUST_PO_ATTR        │
│  SUPS           ◄────FK────│  CUST_SUPPLIER_ATTR  │
│  ITEM_LOC       ◄────FK────│  CUST_ITEM_LOC_ATTR  │
│                      │     │                      │
│  Oracle upgrades     │     │  Your customizations │
│  this schema ────▶   │     │  stay untouched      │
│  Your data stays     │     │                      │
└──────────────────────┘     └──────────────────────┘
CUSTOM TABLES

Creating CUST_ Extension Tables

Creating a Custom Item Attributes Table
SQL
-- Create custom extension table for item-level attributes
CREATE TABLE cust_item_attr (
    item             VARCHAR2(25)  NOT NULL,
    fabric_type      VARCHAR2(50),
    wash_instruction VARCHAR2(100),
    country_of_design VARCHAR2(30),
    sustainability_score NUMBER(3),
    custom_category  VARCHAR2(50),
    create_datetime  DATE DEFAULT SYSDATE NOT NULL,
    last_update_datetime DATE DEFAULT SYSDATE NOT NULL,
    last_update_id   VARCHAR2(30) DEFAULT USER NOT NULL,
    --
    CONSTRAINT pk_cust_item_attr PRIMARY KEY (item),
    CONSTRAINT fk_cia_item FOREIGN KEY (item)
        REFERENCES item_master(item)
);

-- Create index for common query patterns
CREATE INDEX idx_cia_fabric ON cust_item_attr(fabric_type);
CREATE INDEX idx_cia_category ON cust_item_attr(custom_category);

-- Grant access to the RMS application schema
GRANT SELECT, INSERT, UPDATE, DELETE ON cust_item_attr TO rms_app_role;

Naming Convention

Object TypePatternExample
Custom tableCUST_[entity]_[purpose]CUST_ITEM_ATTR
Custom PL/SQL packagePKG_CUST_[domain]PKG_CUST_ITEM_MGMT
Custom viewV_CUST_[entity]V_CUST_ITEM_FULL
Custom sequenceSEQ_CUST_[entity]SEQ_CUST_ATTR_ID
FLEX ATTRIBUTES

Flex Attributes

Flex Attributes are pre-built extension columns on base RMS tables. Oracle has reserved generic columns (VARCHAR2, NUMBER, DATE) on key tables specifically for retailer use:

Using Flex Attributes on ITEM_MASTER
SQL
-- ITEM_MASTER has pre-built flex columns:
-- ITEM_MASTER.UDA_VALUE_01 through UDA_VALUE_15 (VARCHAR2)
-- ITEM_MASTER.UDA_NUM_01 through UDA_NUM_05 (NUMBER)
-- ITEM_MASTER.UDA_DATE_01 through UDA_DATE_05 (DATE)

-- Use flex attributes for simple extensions
UPDATE item_master
SET    uda_value_01 = 'Organic Cotton',     -- Fabric type
       uda_value_02 = 'Machine Wash Cold',   -- Care instruction
       uda_num_01   = 85,                    -- Sustainability score
       uda_date_01  = DATE '2027-06-30'      -- Certification expiry
WHERE  item = '100400012345';

Flex vs. CUST_ Tables

AspectFlex AttributesCUST_ Tables
ComplexitySimple (use existing columns)More complex (new table + joins)
Number of fieldsLimited (15 VARCHAR2 + 5 NUMBER + 5 DATE)Unlimited
PerformanceFast (same table, no join)Slightly slower (requires JOIN)
NamingGeneric (UDA_VALUE_01) — not self-documentingCustom names (fabric_type) — self-documenting
UI IntegrationCan be configured in base RMS UIRequires custom APEX screen
Best forFew simple attributesComplex, multi-valued, or relational data
CUSTOM HOOKS

Custom PL/SQL Hooks

Oracle provides extension hooks — predefined points in base PL/SQL code where custom logic can be injected:

Custom Hook: After Item Creation
SQL
-- Oracle's base code calls this hook after creating an item
CREATE OR REPLACE PACKAGE BODY pkg_cust_item_hooks AS

    PROCEDURE after_item_create (
        p_item      IN  item_master.item%TYPE,
        p_dept      IN  item_master.dept%TYPE,
        p_class     IN  item_master.class%TYPE,
        p_subclass  IN  item_master.subclass%TYPE,
        p_status    IN  item_master.status%TYPE
    ) IS
    BEGIN
        -- Custom logic: Auto-populate extension attributes
        INSERT INTO cust_item_attr (
            item, custom_category, create_datetime
        ) VALUES (
            p_item,
            fn_derive_custom_category(p_dept, p_class),
            SYSDATE
        );
        
        -- Custom logic: Send notification to PLM system
        pkg_cust_integration.notify_plm_item_created(p_item);
        
    EXCEPTION
        WHEN OTHERS THEN
            -- Log error but don't block base item creation
            pkg_cust_error_log.log_error(
                'AFTER_ITEM_CREATE', p_item, SQLERRM
            );
    END after_item_create;

END pkg_cust_item_hooks;
/
REST APIS

REST API Integration (ORDS)

Custom extension data is exposed to external systems via ORDS REST APIs:

Creating a REST API for Custom Item Attributes
SQL
BEGIN
    ORDS.DEFINE_MODULE(
        p_module_name => 'cust_items',
        p_base_path   => '/custom/items/',
        p_status      => 'PUBLISHED'
    );
    
    ORDS.DEFINE_HANDLER(
        p_module_name => 'cust_items',
        p_pattern     => ':item_id/attributes',
        p_method      => 'GET',
        p_source_type => 'json/collection',
        p_source      => '
            SELECT im.item, im.item_desc, im.dept, im.class,
                   ca.fabric_type, ca.wash_instruction,
                   ca.sustainability_score, ca.custom_category
            FROM   item_master im
            LEFT JOIN cust_item_attr ca ON im.item = ca.item
            WHERE  im.item = :item_id'
    );
    COMMIT;
END;
/
CLOUD

Extensions in the Cloud (v19+)

In MFCS cloud, the Extension Model is the ONLY way to customize:

  • Oracle provisions your extension schema via Service Request
  • You access it through APEX SQL Workshop or SQL Developer Web
  • Custom UIs are built in APEX
  • External integration uses ORDS REST APIs
  • There is literally no way to modify base code — you cannot see it
BEST PRACTICES

Best Practices

Important Gotchas

  • !
    NEVER modify Oracle's base tables, packages, or views. Every base modification creates upgrade debt. Use CUST_ tables and extension hooks instead.
  • !
    Custom PL/SQL hooks should NEVER raise unhandled exceptions. If your custom logic fails, it should log the error and allow the base operation to complete. Blocking base operations with custom errors makes the system unusable.
  • !
    Use flex attributes for simple, single-valued extensions (up to 15 VARCHAR2 + 5 NUMBER + 5 DATE). Use CUST_ tables for complex, multi-valued, or relational custom data.
  • !
    Document which flex attribute (UDA_VALUE_01) maps to which business field (fabric_type). Without documentation, generic column names become meaningless within months.
  • !
    Always include audit columns (CREATE_DATETIME, LAST_UPDATE_DATETIME, LAST_UPDATE_ID) on CUST_ tables. They are essential for delta extraction and troubleshooting.

Key Takeaways

  • The Extension Model provides upgrade-safe customization through CUST_ tables, flex attributes, custom hooks, and ORDS REST APIs.
  • Base code modifications create massive technical debt — upgrades that should take 3 months end up taking 18 months.
  • Extension schemas are physically separate from Oracle's base schema — Oracle upgrades never touch your custom objects.
  • Flex attributes (UDA_VALUE_01-15) are quick for simple extensions; CUST_ tables are better for complex relational data.
  • Custom PL/SQL hooks are called by base code at predefined integration points — they must handle errors gracefully and never block base operations.
  • In v19+ Cloud, the Extension Model is mandatory — there is no access to base code or base schema objects.
RetailCoder
All systems operational
v1.0 Live

RC:OMS

Multi-channel order management with double-entry inventory ledger. Amazon, Flipkart, Shopify, WooCommerce — one source of truth.

Launch demo →
v1.0 Live

RC:Storefront

Self-hosted headless e-commerce. Your server, your data, zero transaction fees. Native RC:OMS inventory sync.

Visit Storefront →
Pipeline

RC:Pulse

AI-powered retail analytics and demand forecasting — built natively on top of your RC:OMS and Storefront data.

Request early access →
Built in India 🇮🇳  ·  Architected by Priyanshu PandeyTalk to an engineer →