ORA-40609: Cannot Create JSON-Relational Duality View - Fix Schema Issues
ORA-40609: Cannot Create JSON-Relational Duality View
Section titled “ORA-40609: Cannot Create JSON-Relational Duality View”Error Overview
Section titled “Error Overview”Error Text: ORA-40609: cannot create JSON-Relational Duality View
This error occurs in Oracle 23ai when attempting to create a JSON-Relational Duality View and the underlying schema does not meet the requirements for duality view construction. Duality views provide a JSON document interface over relational tables, but they require specific constraints and relationships to function correctly.
Understanding Duality Views
Section titled “Understanding Duality Views”How Duality Views Work
Section titled “How Duality Views Work”JSON Document Interface | vDuality View Definition | vRelational Tables├── Root Table (Primary Key required)│ └── Foreign Key -> Child Table (Primary Key required)│ └── Foreign Key -> Grandchild Table (Primary Key required)└── All FK relationships define JSON nestingRequirements
Section titled “Requirements”- Every table referenced in the duality view must have a primary key
- Foreign keys define the parent-child JSON document nesting
- Foreign key columns used for joining are automatically resolved and should not be explicitly selected as subobject fields
- Only supported column data types may be used (LONG, LONG RAW, and certain legacy types are excluded)
- DML annotations (
WITH INSERT,WITH UPDATE,WITH DELETE) must use correct syntax
Common Scenarios
Section titled “Common Scenarios”- Missing primary keys on one or more underlying tables
- Foreign key columns selected in subobject when they are resolved automatically from the parent
- Unsupported column types such as LONG or XMLType without proper handling
- Incorrect WITH INSERT/UPDATE/DELETE syntax in the view definition
- Circular foreign key references between tables
- Composite foreign keys not matching a unique or primary key on the referenced table
Diagnostic Steps
Section titled “Diagnostic Steps”1. Verify Primary Keys on All Tables
Section titled “1. Verify Primary Keys on All Tables”-- Check if tables involved in the duality view have primary keysSELECT t.table_name, c.constraint_name, c.constraint_type, LISTAGG(cc.column_name, ', ') WITHIN GROUP (ORDER BY cc.position) AS pk_columnsFROM dba_tables tLEFT JOIN dba_constraints c ON t.table_name = c.table_name AND t.owner = c.owner AND c.constraint_type = 'P'LEFT JOIN dba_cons_columns cc ON c.constraint_name = cc.constraint_name AND c.owner = cc.ownerWHERE t.owner = 'YOUR_SCHEMA' AND t.table_name IN ('TABLE1', 'TABLE2', 'TABLE3') -- Replace with your tablesGROUP BY t.table_name, c.constraint_name, c.constraint_typeORDER BY t.table_name;2. Inspect Foreign Key Relationships
Section titled “2. Inspect Foreign Key Relationships”-- List foreign key relationships between tablesSELECT c.constraint_name AS fk_name, c.table_name AS child_table, LISTAGG(cc.column_name, ', ') WITHIN GROUP (ORDER BY cc.position) AS fk_columns, r.table_name AS parent_table, LISTAGG(rc.column_name, ', ') WITHIN GROUP (ORDER BY rc.position) AS referenced_columnsFROM dba_constraints cJOIN dba_cons_columns cc ON c.constraint_name = cc.constraint_name AND c.owner = cc.ownerJOIN dba_constraints r ON c.r_constraint_name = r.constraint_name AND c.r_owner = r.ownerJOIN dba_cons_columns rc ON r.constraint_name = rc.constraint_name AND r.owner = rc.ownerWHERE c.constraint_type = 'R' AND c.owner = 'YOUR_SCHEMA' AND c.table_name IN ('TABLE1', 'TABLE2', 'TABLE3')GROUP BY c.constraint_name, c.table_name, r.table_nameORDER BY c.table_name;
-- Check that FK columns reference a primary or unique keySELECT c.constraint_name, c.constraint_type, c.table_name, c.r_constraint_name, r.constraint_type AS referenced_constraint_typeFROM dba_constraints cJOIN dba_constraints r ON c.r_constraint_name = r.constraint_name AND c.r_owner = r.ownerWHERE c.constraint_type = 'R' AND c.owner = 'YOUR_SCHEMA' AND r.constraint_type NOT IN ('P', 'U'); -- Problem: FK references non-PK/UK3. Check Column Data Types
Section titled “3. Check Column Data Types”-- Identify unsupported column types for duality viewsSELECT table_name, column_name, data_type, data_lengthFROM dba_tab_columnsWHERE owner = 'YOUR_SCHEMA' AND table_name IN ('TABLE1', 'TABLE2', 'TABLE3') AND data_type IN ('LONG', 'LONG RAW', 'BFILE')ORDER BY table_name, column_id;4. Check Existing Duality Views for Reference
Section titled “4. Check Existing Duality Views for Reference”-- List existing duality views in the schema (Oracle 23ai)SELECT view_name, text_length, textFROM dba_viewsWHERE owner = 'YOUR_SCHEMA' AND view_name LIKE '%_DV'ORDER BY view_name;Immediate Solutions
Section titled “Immediate Solutions”Solution 1: Add Missing Primary Keys
Section titled “Solution 1: Add Missing Primary Keys”The most common cause is tables missing primary keys.
-- Add primary key to a table missing oneALTER TABLE orders ADD CONSTRAINT pk_orders PRIMARY KEY (order_id);
ALTER TABLE order_items ADD CONSTRAINT pk_order_items PRIMARY KEY (item_id);
-- If the table has no suitable single column, use a composite primary keyALTER TABLE order_items ADD CONSTRAINT pk_order_items PRIMARY KEY (order_id, line_number);
-- If no natural key exists, add an identity column (Oracle 23ai)ALTER TABLE legacy_table ADD (id NUMBER GENERATED ALWAYS AS IDENTITY);ALTER TABLE legacy_table ADD CONSTRAINT pk_legacy_table PRIMARY KEY (id);Solution 2: Fix Foreign Key Column Selection in Subobject
Section titled “Solution 2: Fix Foreign Key Column Selection in Subobject”Foreign key columns used for joining are automatically resolved by the duality view. Explicitly selecting them in a subobject causes the error.
Incorrect Definition
Section titled “Incorrect Definition”-- WRONG: Selecting the FK column (customer_id) inside the nested orders subobjectCREATE OR REPLACE JSON RELATIONAL DUALITY VIEW customer_orders_dv ASSELECT JSON { '_id' : c.customer_id, 'name' : c.customer_name, 'email' : c.email, 'orders' : [ SELECT JSON { 'orderId' : o.order_id, 'customerId' : o.customer_id, -- ERROR: FK column selected in subobject 'orderDate' : o.order_date, 'totalAmount' : o.total_amount } FROM orders o WITH INSERT UPDATE DELETE WHERE o.customer_id = c.customer_id ]}FROM customers c WITH INSERT UPDATE DELETE;Correct Definition
Section titled “Correct Definition”-- CORRECT: Omit the FK column (customer_id) from the nested subobjectCREATE OR REPLACE JSON RELATIONAL DUALITY VIEW customer_orders_dv ASSELECT JSON { '_id' : c.customer_id, 'name' : c.customer_name, 'email' : c.email, 'orders' : [ SELECT JSON { 'orderId' : o.order_id, 'orderDate' : o.order_date, 'totalAmount' : o.total_amount } FROM orders o WITH INSERT UPDATE DELETE WHERE o.customer_id = c.customer_id ]}FROM customers c WITH INSERT UPDATE DELETE;Solution 3: Fix WITH INSERT/UPDATE/DELETE Syntax
Section titled “Solution 3: Fix WITH INSERT/UPDATE/DELETE Syntax”-- WRONG: Using commas between DML annotationsCREATE OR REPLACE JSON RELATIONAL DUALITY VIEW order_dv ASSELECT JSON { '_id' : o.order_id, 'status' : o.status}FROM orders o WITH INSERT, UPDATE, DELETE; -- ERROR: Commas not allowed
-- CORRECT: Space-separated DML annotations (no commas)CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW order_dv ASSELECT JSON { '_id' : o.order_id, 'status' : o.status}FROM orders o WITH INSERT UPDATE DELETE;
-- CORRECT: Read-only view (no DML annotations)CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW order_readonly_dv ASSELECT JSON { '_id' : o.order_id, 'status' : o.status}FROM orders o;Solution 4: Complete Working Example
Section titled “Solution 4: Complete Working Example”-- Step 1: Create properly constrained tablesCREATE TABLE customers ( customer_id NUMBER GENERATED ALWAYS AS IDENTITY, customer_name VARCHAR2(100) NOT NULL, email VARCHAR2(255) NOT NULL, CONSTRAINT pk_customers PRIMARY KEY (customer_id));
CREATE TABLE orders ( order_id NUMBER GENERATED ALWAYS AS IDENTITY, customer_id NUMBER NOT NULL, order_date DATE DEFAULT SYSDATE, total_amount NUMBER(10,2), status VARCHAR2(20) DEFAULT 'PENDING', CONSTRAINT pk_orders PRIMARY KEY (order_id), CONSTRAINT fk_orders_customer FOREIGN KEY (customer_id) REFERENCES customers(customer_id));
CREATE TABLE order_items ( item_id NUMBER GENERATED ALWAYS AS IDENTITY, order_id NUMBER NOT NULL, product VARCHAR2(100), quantity NUMBER, unit_price NUMBER(10,2), CONSTRAINT pk_order_items PRIMARY KEY (item_id), CONSTRAINT fk_items_order FOREIGN KEY (order_id) REFERENCES orders(order_id));
-- Step 2: Create a multi-level duality viewCREATE OR REPLACE JSON RELATIONAL DUALITY VIEW customer_orders_dv ASSELECT JSON { '_id' : c.customer_id, 'name' : c.customer_name, 'email' : c.email, 'orders' : [ SELECT JSON { 'orderId' : o.order_id, 'orderDate' : o.order_date, 'totalAmount' : o.total_amount, 'status' : o.status, 'items' : [ SELECT JSON { 'itemId' : i.item_id, 'product' : i.product, 'quantity' : i.quantity, 'unitPrice' : i.unit_price } FROM order_items i WITH INSERT UPDATE DELETE WHERE i.order_id = o.order_id ] } FROM orders o WITH INSERT UPDATE DELETE WHERE o.customer_id = c.customer_id ]}FROM customers c WITH INSERT UPDATE DELETE;Long-Term Solutions
Section titled “Long-Term Solutions”1. Validate Schema Before Creating Duality Views
Section titled “1. Validate Schema Before Creating Duality Views”-- Pre-flight check: Ensure all tables have primary keysDECLARE v_missing_pk NUMBER := 0;BEGIN FOR rec IN ( SELECT t.table_name FROM user_tables t WHERE NOT EXISTS ( SELECT 1 FROM user_constraints c WHERE c.table_name = t.table_name AND c.constraint_type = 'P' ) AND t.table_name IN ('CUSTOMERS', 'ORDERS', 'ORDER_ITEMS') -- Your tables ) LOOP DBMS_OUTPUT.PUT_LINE('MISSING PK: ' || rec.table_name); v_missing_pk := v_missing_pk + 1; END LOOP;
IF v_missing_pk = 0 THEN DBMS_OUTPUT.PUT_LINE('All tables have primary keys - safe to create duality view'); ELSE DBMS_OUTPUT.PUT_LINE(v_missing_pk || ' table(s) missing primary keys - fix before creating duality view'); END IF;END;/2. Establish Foreign Key Design Standards
Section titled “2. Establish Foreign Key Design Standards”-- Verify all FK relationships are properly definedSELECT child.table_name AS child_table, child.constraint_name AS fk_name, parent.table_name AS parent_table, parent.constraint_name AS referenced_constraint, parent.constraint_type AS ref_type, CASE parent.constraint_type WHEN 'P' THEN 'OK - References Primary Key' WHEN 'U' THEN 'OK - References Unique Key' ELSE 'WARNING - Unusual reference type' END AS assessmentFROM user_constraints childJOIN user_constraints parent ON child.r_constraint_name = parent.constraint_nameWHERE child.constraint_type = 'R'ORDER BY child.table_name;Prevention Strategies
Section titled “Prevention Strategies”1. Schema Design Best Practices
Section titled “1. Schema Design Best Practices”Before creating a duality view, verify:1. Every table has a PRIMARY KEY constraint2. Foreign keys reference PRIMARY KEY or UNIQUE KEY columns3. No LONG or LONG RAW columns exist on referenced tables4. No circular foreign key references between tables5. FK columns are NOT selected in nested subobject projections2. Development Workflow
Section titled “2. Development Workflow”- Design relationally first - Get your tables, primary keys, and foreign keys right before thinking about duality views
- Test incrementally - Start with a simple single-table duality view, then add nested subobjects one at a time
- Use identity columns - Oracle 23ai identity columns guarantee unique primary keys without sequence management
- Name constraints explicitly - Named constraints produce clearer error messages when debugging
3. Pre-Creation Checklist
Section titled “3. Pre-Creation Checklist”-- Quick check: Tables, PKs, and FKs summarySELECT t.table_name, NVL(pk.pk_name, '*** MISSING PK ***') AS primary_key, NVL(pk.pk_columns, 'N/A') AS pk_columns, COUNT(fk.constraint_name) AS fk_countFROM user_tables tLEFT JOIN ( SELECT c.table_name, c.constraint_name AS pk_name, LISTAGG(cc.column_name, ', ') WITHIN GROUP (ORDER BY cc.position) AS pk_columns FROM user_constraints c JOIN user_cons_columns cc ON c.constraint_name = cc.constraint_name WHERE c.constraint_type = 'P' GROUP BY c.table_name, c.constraint_name) pk ON t.table_name = pk.table_nameLEFT JOIN user_constraints fk ON t.table_name = fk.table_name AND fk.constraint_type = 'R'WHERE t.table_name IN ('CUSTOMERS', 'ORDERS', 'ORDER_ITEMS') -- Your tablesGROUP BY t.table_name, pk.pk_name, pk.pk_columnsORDER BY t.table_name;Related Errors
Section titled “Related Errors”- ORA-42647 - Missing
_idfield in duality view definition - ORA-00942 - Table or view does not exist (underlying table missing)
- ORA-02291 - Integrity constraint violated - parent key not found
- ORA-00001 - Unique constraint violated (during DML through duality view)
- ORA-01031 - Insufficient privileges (missing CREATE VIEW privilege)
Quick Reference
Section titled “Quick Reference”Emergency Response Steps
Section titled “Emergency Response Steps”- Check the exact error details in the session or alert log for specifics
- Verify all underlying tables have primary key constraints
- Confirm foreign key relationships are properly defined
- Ensure FK columns are not explicitly selected in nested subobjects
- Validate column data types are supported
- Check WITH INSERT/UPDATE/DELETE syntax (no commas)
- Test with a simplified single-table duality view first
Quick Commands
Section titled “Quick Commands”-- Check for missing primary keysSELECT table_name FROM user_tablesWHERE table_name NOT IN ( SELECT table_name FROM user_constraints WHERE constraint_type = 'P');
-- Add a primary keyALTER TABLE table_name ADD CONSTRAINT pk_table PRIMARY KEY (id_column);
-- List FK columns (do NOT select these in nested subobjects)SELECT table_name, constraint_name, column_nameFROM user_cons_columnsWHERE constraint_name IN ( SELECT constraint_name FROM user_constraints WHERE constraint_type = 'R')ORDER BY table_name, constraint_name, position;
-- Minimal duality view testCREATE JSON RELATIONAL DUALITY VIEW test_dv ASSELECT JSON {'_id' : t.id, 'name' : t.name}FROM my_table t WITH INSERT UPDATE DELETE;Prevention Guidelines
Section titled “Prevention Guidelines”- Always define primary keys - Every table in a duality view requires one
- Design foreign keys carefully - They define the JSON document nesting structure
- Do not select FK columns in subobjects - The view resolves them automatically from the parent
- Use identity columns - Simplifies primary key management in Oracle 23ai
- Test incrementally - Build duality views one nesting level at a time
- Validate schema first - Run pre-flight checks before creating complex duality views