📄 JSON (JavaScript Object Notation)
Native JSON in Oracle
Oracle supports JSON natively, allowing flexible storage of structured data:
-- Create table with JSON column
CREATE TABLE employees (
employee_id NUMBER PRIMARY KEY,
name VARCHAR2(100),
employee_data JSON -- JSON data type
);
-- Insert JSON document
INSERT INTO employees
VALUES (
101,
'John Smith',
'{"email":"john@company.com","department":"IT","salary":85000,"skills":["SQL","Java","Python"]}'
);
-- Query JSON data
SELECT
employee_id,
name,
employee_data.email,
employee_data.salary,
employee_data.skills[0]
FROM employees;
JSON Functions
| Function | Purpose | Example |
|---|---|---|
| JSON_VALUE | Extract scalar value | JSON_VALUE(data, '$.email') |
| JSON_QUERY | Extract object/array | JSON_QUERY(data, '$.skills') |
| JSON_TABLE | Convert JSON to table | JSON_TABLE (for nested arrays) |
| JSON_OBJECT | Create JSON from columns | JSON_OBJECT('name' VALUE name, 'email' VALUE email) |
| JSON_ARRAY | Create JSON array | JSON_ARRAY(col1, col2, col3) |
JSON Path Expressions
-- Access nested JSON with path notation
SELECT
JSON_VALUE(employee_data, '$.email') AS email,
JSON_VALUE(employee_data, '$.department') AS dept,
JSON_QUERY(employee_data, '$.skills') AS all_skills
FROM employees;
-- Unnest JSON arrays with JSON_TABLE
SELECT
e.employee_id,
e.name,
jt.skill
FROM employees e
CROSS JOIN JSON_TABLE(
e.employee_data,
'$.skills[*]' COLUMNS (skill VARCHAR2(50) PATH '$')
) jt;
📑 XML (Extensible Markup Language)
Storing XML Data
-- Create table with XMLType column
CREATE TABLE documents (
doc_id NUMBER PRIMARY KEY,
doc_content XMLType
);
-- Insert XML document
INSERT INTO documents
VALUES (
1,
XMLType(
'
101
John Smith
john@company.com
SQL
Java
'
)
);
-- Query XML using XPath
SELECT
doc_id,
extractValue(doc_content, '/employee/name/text()') AS name,
extractValue(doc_content, '/employee/email/text()') AS email
FROM documents;
XML Functions
| Function | Purpose |
|---|---|
| extractValue | Extract scalar value from XML path |
| extract | Extract XML fragment |
| existsNode | Check if XML node exists |
| XMLConcat | Concatenate XML fragments |
| XMLElement | Create XML element from columns |
💾 LOB (Large Object) Data Types
LOB Types
| Type | Max Size | Content Type | Use Case |
|---|---|---|---|
| CLOB | 4GB | Character (text) | Large text, documents, code |
| BLOB | 4GB | Binary (images, files) | Images, videos, binary files |
| NCLOB | 4GB | National character set | Multi-language text |
| BFILE | 4GB | Binary (external file) | Reference to OS files |
Working with LOBs
-- Create table with LOB columns
CREATE TABLE documents (
doc_id NUMBER PRIMARY KEY,
doc_name VARCHAR2(100),
content CLOB, -- Large text
attachment BLOB -- Binary file
);
-- Insert LOB data (small chunks)
INSERT INTO documents (doc_id, doc_name, content)
VALUES (1, 'Report', 'This is a large text document...');
-- Check LOB size
SELECT
doc_id,
DBMS_LOB.getlength(content) AS content_size,
DBMS_LOB.getlength(attachment) AS attachment_size
FROM documents;
-- Read LOB data
DECLARE
v_content CLOB;
v_chunk VARCHAR2(32767);
BEGIN
SELECT content INTO v_content
FROM documents WHERE doc_id = 1;
DBMS_LOB.read(v_content, 1000, 1, v_chunk);
DBMS_OUTPUT.put_line(v_chunk);
END;
💡 Tip: Use DBMS_LOB package for LOB manipulation. CLOB good for text, BLOB for binary. Use temporary LOBs for performance.
📦 Collections (VARRAY & Nested Tables)
VARRAY (Variable-size Array)
Fixed-size array with maximum element count
-- Define VARRAY type
CREATE TYPE skills_array AS VARRAY(10) OF VARCHAR2(50);
/
-- Use VARRAY in table
CREATE TABLE employees (
employee_id NUMBER PRIMARY KEY,
name VARCHAR2(100),
skills skills_array
);
-- Insert VARRAY data
INSERT INTO employees
VALUES (
101,
'John Smith',
skills_array('SQL', 'Java', 'Python')
);
-- Access VARRAY elements
SELECT
employee_id,
name,
skills(1) AS first_skill,
TABLE(skills) AS all_skills
FROM employees;
Nested Tables
Variable-size collection without predefined maximum
-- Define Nested Table type
CREATE TYPE projects_table AS TABLE OF VARCHAR2(100);
/
-- Create table storage for nested table
CREATE TABLE employees (
employee_id NUMBER PRIMARY KEY,
name VARCHAR2(100),
projects projects_table
)
NESTED TABLE projects STORE AS projects_nt;
-- Insert nested table data
INSERT INTO employees
VALUES (
101,
'John Smith',
projects_table('Project A', 'Project B', 'Project C')
);
-- Query nested table
SELECT
e.employee_id,
e.name,
p.column_value AS project
FROM employees e,
TABLE(e.projects) p;
VARRAY vs Nested Table
| Feature | VARRAY | Nested Table |
|---|---|---|
| Max Size | Fixed limit | Variable (unlimited) |
| Storage | Inline with parent | Separate storage table |
| Ordering | Preserves order, indexed | No inherent order |
| Performance | Fast access by index | Better for large sets |
| Use Case | Fixed list (max 10 skills) | Variable list (any projects) |
👤 User-Defined Types (UDT)
Object Types
-- Define object type (like a class)
CREATE TYPE address_type AS OBJECT (
street VARCHAR2(100),
city VARCHAR2(50),
state VARCHAR2(2),
zip_code VARCHAR2(10)
);
/
-- Use object type in table
CREATE TABLE customers (
customer_id NUMBER PRIMARY KEY,
name VARCHAR2(100),
address address_type,
phone VARCHAR2(20)
);
-- Insert object data
INSERT INTO customers
VALUES (
1,
'John Smith',
address_type('123 Main St', 'New York', 'NY', '10001'),
'555-1234'
);
-- Access object attributes
SELECT
customer_id,
name,
address.street,
address.city,
address.zip_code
FROM customers;
Method Definition in Object Type
-- Define object type with methods
CREATE TYPE employee_type AS OBJECT (
emp_id NUMBER,
name VARCHAR2(100),
salary NUMBER,
MEMBER FUNCTION get_annual_salary RETURN NUMBER,
MEMBER FUNCTION is_high_earner RETURN BOOLEAN
);
/
-- Implement methods
CREATE TYPE BODY employee_type AS
MEMBER FUNCTION get_annual_salary RETURN NUMBER IS
BEGIN
RETURN salary * 12;
END;
MEMBER FUNCTION is_high_earner RETURN BOOLEAN IS
BEGIN
RETURN salary > 10000;
END;
END;
/
✅ Best Practices for Advanced Types
- JSON vs XML: Use JSON for modern applications (simpler, better performance), XML for legacy systems
- LOB Management: Use DBMS_LOB package, enable LOB caching for frequently accessed data
- Collections: Use VARRAY for fixed, small collections; Nested Tables for variable, larger sets
- UDT Design: Keep types simple, avoid excessive nesting
- Indexing: Create function-based indexes on JSON/XML columns for faster queries
- Storage: Consider tablespace design for LOBs and nested tables
- Performance: Avoid LOBs in WHERE clause; use JSON_TABLE for better performance
JSON Performance Tips
-- Create functional index on JSON field for performance
CREATE INDEX emp_email_idx ON employees(
JSON_VALUE(employee_data, '$.email')
);
-- Use JSON_TABLE for better performance with large result sets
SELECT *
FROM JSON_TABLE(
SELECT employee_data FROM employees,
'$[*]' COLUMNS (
email VARCHAR2(100) PATH '$.email',
name VARCHAR2(100) PATH '$.name',
salary NUMBER PATH '$.salary'
)
);
✓ Learning Checklist - Module 4