Whenever we hear Oracle Database, we imagine storing data in rows and columns. The data stored in cells generally is in primitive data types(char, varchar2, int, date, etc.). What if we need to store JSON data in the table. The first thing that may come into our minds is to convert JSON data to string(varchar2) or have data as clob/blob and insert it into the table. But with this if we need to query a particular field or update it, tricky one. This blog is a part of a series. The scope includes, creation of table having column with JSON datatype, insertion of JSON data and querying the JSON data.
Umm.. How to do? 🔗

Let’s put the developer hat on! and start exploring. In this blog, Oracle Database 23c free is used.
Create a table with a column to store JSON data 🔗
JSON data can be used natively with RDBMS features in Oracle Database 23c. Let’s start the journey by creating a simple database table for storing JSON data.
Create a sequence SEQ_PO for the id column.
create sequence SEQ_PO start with 1000 increment by 1 NOCACHE NOMAXVALUE;
Create a table q_purchaseorder to store purchase order documents in JSON format.
CREATE TABLE q_purchaseorder
(id NUMBER DEFAULT ON NULL SEQ_PO.NEXTVAL PRIMARY KEY,
date_loaded TIMESTAMP (6) WITH TIME ZONE,
po_document JSON);
If, we want to store the JSON data in Varchar2, then we need to add a constraint “ensure_json” to check if the data is in JSON format. For example:
CREATE TABLE q_purchaseorder
(id NUMBER DEFAULT ON NULL SEQ_PO.NEXTVAL PRIMARY KEY,
date_loaded TIMESTAMP (6) WITH TIME ZONE,
po_document VARCHAR2 (23767)
CONSTRAINT ensure_json CHECK (po_document is json));
The table q_purchaseorder is created.
Insert data to the JSON column 🔗
Let’s insert some purchase orders JSON data to the newly created table in po_document column.
INSERT INTO q_purchaseorder (date_loaded,po_document) VALUES (
SYSTIMESTAMP, '{
"pONumber": "1001",
"reference": "dm-1001",
"requestor": "One More Query",
"user": "dm_1",
"costCenter": "CC1",
"shippingDetails": {
"name": "Test 1",
"address": {
"street": "Street 1",
"city": "Amritsar",
"state": "Punjab",
"zipCode": "143001",
"country": "India"
},
"phone": "+91-99999-99999"
},
"message": "Courier",
"lineItems": [
{
"itemNumber": 1,
"part": {
"description": "Test product1",
"unitPrice": 200,
"uPCCode": "123456789"
},
"quantity": 8.0
},
{
"itemNumber": 2,
"part": {
"description": "Test product2",
"unitPrice": 250,
"uPCCode": "987654321"
},
"quantity": 5
}
]
}'
);
The above JSON record gets inserted into the table.
select * from q_purchaseorder;

Query the JSON data 🔗
The easiest way to query the JSON data is to use dot notations. The JSON data in the column must be well formed. If the data type is not JSON, varchar2, clob/blob column must have “is json “ constraint. Taking the data inserted in the previous step as an example, below are the various queries to extract values from different JSON fields.
Query the PO number. 🔗
SELECT po.PO_DOCUMENT.pONumber FROM q_purchaseorder po;
Query the unit price for second line item. 🔗
SELECT po.PO_DOCUMENT.lineItems[1].part.unitPrice FROM q_purchaseorder po;
The above two examples output the data as JSON object instead of SQL number or SQL STRING, as the column datatype is JSON. If datatype of the column is not JSON, the query will give a result in VARCHAR2 format. An item method, such as number(), string(), etc., can convert JSON/VARCHAR2 output from the query into the desired format. For example:
Query the quantity for the second line item and output in number format. 🔗
SELECT po.PO_DOCUMENT.lineItems[0].quantity.number() FROM q_purchaseorder po where po.id=1000;;
Another way to query data is to use JSON_VALUE SQL function. For example:
Query the PO Number in number format using JSON_VALUE SQL function. 🔗
SELECT JSON_VALUE(po_document, '$.pONumber.number()') from q_purchaseorder where po.id=1000;;
Pretty simple, yeah? Let’s make it a bit more complex.
How to fetch an item description from purchase order JSON where unit price is less than 225?
Scratching the head!!!! Let’s use json_query sql function along with filter conditions to accomplish the task.
SELECT json_query(po.po_document, '$.lineItems[*].part?(@.unitPrice < 225).description' with ARRAY wrapper)
FROM q_purchaseorder po
WHERE po.id=1000;
WITH ARRAY WRAPPER is used to wrap the results in array, as output may contain more than one values.
References: 🔗
- https://docs.oracle.com/en/database/oracle/oracle-database/23/adjsn/json-data.html
- https://www.oracle.com/in/database/free/
Please feel free to share your valuable feedback ! 😊😊😊