Create an Initial Duality View

Create the initial sales duality view that the schema evolution examples use as a starting point.

Dave starts a small lemonade operation.

It begins with one cart, but Dave is already planning for more locations. He keeps stand information separate from the sale because a stand has its own identity, location, and price per cup. That makes the first model simple enough to understand, but still ready for the business to grow.

A sale records who bought lemonade, how many cups were sold, how much was charged, and which stand handled the sale.

This topic introduces the first JSON-relational duality view. It is not the long-term compatibility point for later evolution. It simply shows the first document shape before the business starts changing.

Relational Schema

The baseline schema starts with two tables.

Table Role
sales Stores sale-level information such as date, quantity, amount, customer name, email address, and stand reference.
stands Stores stand-level information such as location and price per cup.

Initial Relational DDL

CREATE TABLE stands (
  stand_id       INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
  location       VARCHAR2(100) NOT NULL,
  price_per_cup  NUMBER(10, 2) DEFAULT 2.5 NOT NULL,
  CONSTRAINT stands_pk PRIMARY KEY (stand_id)
);

CREATE TABLE sales (
  sale_id        INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
  sale_date      DATE DEFAULT SYSDATE,
  quantity       NUMBER NOT NULL,
  amount         NUMBER(10, 2) NOT NULL,
  customer_name  VARCHAR2(50) DEFAULT 'User' NOT NULL,
  email_address  VARCHAR2(100) DEFAULT NULL,
  stand_id       INTEGER DEFAULT 1 NOT NULL,
  CONSTRAINT sales_pk PRIMARY KEY (sale_id),
  CONSTRAINT sales_stand_fk FOREIGN KEY (stand_id) REFERENCES stands (stand_id)
);

The relationship is:

sales.stand_id -> stands.stand_id

A sale belongs to a stand. The application can still work with one JSON document.

First Duality View

sales_view exposes the sale as a JSON document and nests the stand details inside stand_info.

CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW sales_view AS
sales @insert @update @delete
{
    _id: sale_id,
    date: sale_date,
    quantity,
    amount,
    customer_name,
    email_address,
    stand_info: stands @insert @update @nodelete
    {
        _id: stand_id,
        location,
        price_per_cup
    }
};

The application sees a document shaped like this:

{
    "_id": 1,
    "date": "2026-01-12",
    "quantity": 8,
    "amount": 22.00,
    "customer_name": "nora",
    "email_address": "nora@example.com",
    "stand_info": {
        "_id": 1,
        "location": "MARKET CART, NORTH PLAZA",
        "price_per_cup": 2.75
    }
}

What the View Introduces

The application sees a JSON sale document. The database stores the sale and stand details in relational tables. The duality view connects the document shape to the relational shape.

Duality view feature Meaning here
sales @insert @update @delete The root object is backed by the sales table and supports document-level inserts, updates, and deletes.
stand_info: stands Stand data appears as a nested object inside the sale document.
@nodelete Keeps a stand from being deleted when a sale document is deleted.

This is the first idea needed for the rest of the evolution. The application API can be JSON while the storage model remains relational.

Evolution Check

This scenario confirms the basic document shape.

sales_view is only the introductory view. The durable compatibility API begins in the next scenario, where product fields are added and the evolved sale shape becomes sales_v1.