Skip to content
Oracle Database Guide — SQL, PL/SQL, and Enterprise Features

Oracle Database Guide — SQL, PL/SQL, and Enterprise Features

DodaTech Updated Jun 7, 2026 11 min read

Oracle Database is a multi-model enterprise relational database management system known for its high performance, scalability, security features, and support for SQL and PL/SQL across mission-critical applications worldwide.

What You’ll Learn

By the end of this tutorial, you’ll understand Oracle Database architecture, connect using SQL*Plus, write SQL and PL/SQL queries, create tables with constraints and indexes, work with sequences and views, and use Oracle-specific features like materialized views and partitioning.

Why Oracle Matters

Oracle powers the world’s largest financial systems, government databases, and enterprise resource planning platforms. DodaZIP’s cloud backend uses Oracle for compliance-critical audit logs, while Durga Antivirus Pro leverages Oracle for its threat intelligence warehouse. Mastering Oracle opens doors to enterprise database administration and high-paying backend roles.

Oracle Learning Path

    flowchart LR
  A[SQL Basics] --> B[MySQL]
  B --> C[Oracle]
  C --> D[SQL Server]
  D --> E[MongoDB]
  E --> F[Database Design]
  C --> G{You Are Here}
  style G fill:#f90,color:#fff
  
Prerequisites: SQL basics (SELECT, INSERT, UPDATE, DELETE). Familiarity with relational database concepts helps. A free Oracle XE installation is recommended for practice.

What Is Oracle Database? (The “Why” First)

Think of Oracle Database as a fortress for enterprise data. Unlike MySQL or PostgreSQL which are designed for web applications, Oracle is built for environments where data loss is simply not an option — banking systems, air traffic control, hospital records. It offers features like Real Application Clusters (RAC) for high availability, Advanced Security for encryption, and partitioning for managing petabytes of data.

Oracle Database Editions

EditionUse CaseKey Limitation
Enterprise EditionLarge-scale productionMost expensive, full feature set
Standard Edition 2Mid-range serversLimited to 2 sockets, no RAC
Express Edition (XE)Learning, small apps12GB user data, 2GB RAM limit
FreeDeveloper sandboxSame limits as XE, no cost

Connecting with SQL*Plus

SQL*Plus is Oracle’s command-line interface — your direct line to the database:

# Connect as system administrator
sqlplus system/your_password@localhost:1521/XEPDB1

# Expected output:
# Connected to:
# Oracle Database 21c Express Edition Release 21.0.0.0.0
-- View your current user and database
SELECT USER, SYSDATE FROM DUAL;

-- Output:
-- USER    | SYSDATE
-- SYSTEM  | 2026-06-07 10:30:00

DUAL is a special Oracle table with one row, used for queries that don’t need a real table. It’s unique to Oracle — no other database has it.

Creating Tables with Oracle-Specific Features

Oracle has its own data types and table creation syntax:

-- Create a customers table with Oracle features
CREATE TABLE customers (
    customer_id NUMBER(10) GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    first_name VARCHAR2(50) NOT NULL,
    last_name VARCHAR2(50) NOT NULL,
    email VARCHAR2(100) NOT NULL,
    phone VARCHAR2(20),
    credit_limit NUMBER(10, 2) CHECK (credit_limit > 0),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    status VARCHAR2(20) DEFAULT 'ACTIVE'
);

-- Create an orders table
CREATE TABLE orders (
    order_id NUMBER(10) GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    customer_id NUMBER(10) NOT NULL,
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    total_amount NUMBER(12, 2) NOT NULL,
    status VARCHAR2(20) DEFAULT 'PENDING',
    CONSTRAINT fk_orders_customer
        FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);

-- Add a comment on a column
COMMENT ON COLUMN customers.credit_limit IS 'Maximum credit allowed for this customer';

Oracle-Specific Features:

  • NUMBER(precision, scale) — Oracle’s numeric type (replaces INT, DECIMAL from other databases)
  • VARCHAR2 — Oracle’s variable-length string type (use this instead of VARCHAR)
  • GENERATED BY DEFAULT AS IDENTITY — Oracle 12c+ auto-increment (replaces AUTO_INCREMENT)
  • COMMENT ON COLUMN — documentation stored in the data dictionary
  • CHECK constraints — inline validation without separate triggers

Sequences — Oracle’s Auto-Increment

Before identity columns (pre-12c), Oracle used sequences for generating unique numbers:

-- Create a sequence
CREATE SEQUENCE customer_seq
    START WITH 1000
    INCREMENT BY 1
    NOCACHE
    NOCYCLE;

-- Use the sequence in an INSERT
INSERT INTO customers (customer_id, first_name, last_name, email)
VALUES (customer_seq.NEXTVAL, 'Alice', 'Johnson', 'alice@example.com');

-- Check the current value without incrementing
SELECT customer_seq.CURRVAL FROM DUAL;

Output:

CURRVAL
1000

Sequences are still widely used in legacy Oracle systems. They’re more flexible than AUTO_INCREMENT — you can cache values, cycle after reaching a maximum, and control increment size.

SQL vs PL/SQL in Oracle

FeatureSQLPL/SQL
PurposeData querying and manipulationProcedural logic + SQL
ExecutionStatement at a timeBlock at a time
VariablesNo (except bind variables)Yes (DECLARE section)
Control flowNoIF, LOOP, WHILE, FOR
Error handlingMinimalEXCEPTION block
SpeedFast for single statementsFaster for multi-step operations

PL/SQL Example — Stored Procedure

CREATE OR REPLACE PROCEDURE apply_credit_increase (
    p_customer_id NUMBER,
    p_increase_percent NUMBER
) AS
    v_current_limit NUMBER(10, 2);
BEGIN
    -- Get the current credit limit
    SELECT credit_limit INTO v_current_limit
    FROM customers
    WHERE customer_id = p_customer_id;

    -- Update with the increase
    UPDATE customers
    SET credit_limit = v_current_limit * (1 + p_increase_percent / 100)
    WHERE customer_id = p_customer_id;

    COMMIT;
    DBMS_OUTPUT.PUT_LINE('Credit limit increased for customer ' || p_customer_id);
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('Customer not found: ' || p_customer_id);
    WHEN OTHERS THEN
        ROLLBACK;
        DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
END apply_credit_increase;
/

-- Call the procedure
EXEC apply_credit_increase(1000, 10);

Indexes — Optimizing Query Performance

Oracle offers multiple index types:

-- B-tree index (default) — good for equality and range queries
CREATE INDEX idx_customers_email ON customers(email);

-- Bitmap index — good for low-cardinality columns (status, gender)
CREATE BITMAP INDEX idx_orders_status ON orders(status);

-- Function-based index — index on an expression
CREATE INDEX idx_customers_upper_email ON customers(UPPER(email));

-- Check index usage
SELECT index_name, index_type, uniqueness
FROM user_indexes
WHERE table_name = 'CUSTOMERS';

Output:

INDEX_NAME            | INDEX_TYPE | UNIQUENESS
IDX_CUSTOMERS_EMAIL   | NORMAL     | NONUNIQUE
IDX_CUSTOMERS_UPPER_EMAIL | FUNCTION-BASED NORMAL | NONUNIQUE

Views and Materialized Views

Regular View — A Saved Query

CREATE OR REPLACE VIEW vw_customer_orders AS
SELECT
    c.customer_id,
    c.first_name || ' ' || c.last_name AS full_name,
    COUNT(o.order_id) AS order_count,
    NVL(SUM(o.total_amount), 0) AS total_spent
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, c.first_name, c.last_name;

-- Query the view (looks like a table)
SELECT * FROM vw_customer_orders WHERE total_spent > 1000;

Materialized View — Physically Stored Results

-- Refreshed daily
CREATE MATERIALIZED VIEW mv_monthly_sales
REFRESH COMPLETE
START WITH SYSDATE
NEXT SYSDATE + 1
AS
SELECT
    TRUNC(order_date, 'MM') AS month,
    COUNT(*) AS order_count,
    SUM(total_amount) AS revenue
FROM orders
GROUP BY TRUNC(order_date, 'MM');

Materialized views are a killer Oracle feature. Unlike regular views (which run the query every time), materialized views store the result on disk and refresh on a schedule. They dramatically speed up dashboard queries on large datasets.

Oracle Architecture

    flowchart TB
    subgraph Users
        U1[User Process]
        U2[User Process]
    end
    subgraph Instance
        SGA[Shared Global Area]
        PMON[PMON]
        SMON[SMON]
        DBWR[DB Writer]
        LGWR[Log Writer]
        CKPT[Checkpoint]
    end
    subgraph Storage
        DF[Data Files]
        CF[Control Files]
        RF[Redo Log Files]
    end
    U1 --> SGA
    U2 --> SGA
    SGA --> DBWR --> DF
    SGA --> LGWR --> RF
    PMON --> SGA
    SMON --> SGA
    CKPT --> DF
  

Oracle’s architecture separates the instance (memory + background processes) from the database (disk storage). This allows multiple instances to access the same database (RAC) for high availability.

Common Oracle Errors

1. ORA-00942: Table or View Does Not Exist

-- The table might not exist, or you don't have SELECT privilege
SELECT * FROM secret_table;
-- ORA-00942: table or view does not exist

Fix: Check the table name spelling and verify privileges with SELECT * FROM ALL_TABLES WHERE TABLE_NAME = 'SECRET_TABLE'.

2. ORA-00001: Unique Constraint Violated

INSERT INTO customers (customer_id, email) VALUES (1000, 'alice@example.com');
-- If customer_id 1000 or email already exists:
-- ORA-00001: unique constraint (SYSTEM.SYS_C0012345) violated

Fix: Use MERGE (upsert) or check for existing records first.

3. ORA-00933: SQL Command Not Properly Ended

-- WRONG — Oracle doesn't support JOIN ... USING with AS table alias before 23c
SELECT * FROM orders o JOIN customers c USING (customer_id);

-- RIGHT
SELECT * FROM orders o JOIN customers c ON o.customer_id = c.customer_id;

4. ORA-01400: Cannot Insert NULL

INSERT INTO customers (first_name, last_name) VALUES (NULL, 'Smith');
-- ORA-01400: cannot insert NULL into ("SYSTEM"."CUSTOMERS"."FIRST_NAME")

Fix: Always provide values for NOT NULL columns, or use NVL / COALESCE to supply defaults.

5. ORA-01555: Snapshot Too Old

This occurs when a long-running query tries to read a previous version of a block that has been overwritten. Fix: Increase UNDO_RETENTION or tune the query to run faster.

6. ORA-01722: Invalid Number

SELECT * FROM customers WHERE customer_id = 'ABC';
-- ORA-01722: invalid number

Fix: Don’t compare NUMBER columns with string literals. Remove non-numeric characters before conversion.

7. ORA-01017: Invalid Username/Password

Fix: Reset the password using ALTER USER username IDENTIFIED BY new_password as a DBA.

Practice Questions

1. What is the difference between SQL and PL/SQL?

SQL is for querying and manipulating data one statement at a time. PL/SQL is Oracle’s procedural extension that adds variables, loops, conditionals, and error handling — allowing multiple SQL operations in a single block.

2. What is a sequence in Oracle?

A sequence is a database object that generates unique numeric values. It’s commonly used for primary key generation, replacing AUTO_INCREMENT from other databases. You access it with NEXTVAL (get next) and CURRVAL (get current).

3. How is a materialized view different from a regular view?

A regular view is a saved query that runs each time you access it. A materialized view stores the query results physically on disk and refreshes on a schedule — it’s faster for queries but uses storage and can be stale.

4. Challenge: Write a PL/SQL block that loops through all customers and prints their names.

BEGIN
    FOR rec IN (SELECT first_name, last_name FROM customers) LOOP
        DBMS_OUTPUT.PUT_LINE('Customer: ' || rec.first_name || ' ' || rec.last_name);
    END LOOP;
END;
/

5. What does DUAL do in Oracle?

DUAL is a dummy table with one row, used for SELECT statements that don’t need data from a real table — like SELECT SYSDATE FROM DUAL. It’s Oracle-specific and required in many contexts where other databases don’t need a FROM clause.

Real-World Task: Create an Audit Log System

Design a schema for tracking changes to sensitive data — like what Durga Antivirus Pro uses for security audits:

-- Audit log table
CREATE TABLE audit_log (
    audit_id NUMBER(10) GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    table_name VARCHAR2(100) NOT NULL,
    action VARCHAR2(10) NOT NULL CHECK (action IN ('INSERT', 'UPDATE', 'DELETE')),
    record_id NUMBER(10) NOT NULL,
    old_values CLOB,
    new_values CLOB,
    changed_by VARCHAR2(100) DEFAULT USER,
    changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- Trigger to capture changes on customers table
CREATE OR REPLACE TRIGGER trg_customers_audit
AFTER INSERT OR UPDATE OR DELETE ON customers
FOR EACH ROW
BEGIN
    IF INSERTING THEN
        INSERT INTO audit_log (table_name, action, record_id, new_values)
        VALUES ('CUSTOMERS', 'INSERT', :NEW.customer_id,
                'first_name=' || :NEW.first_name || ', email=' || :NEW.email);
    ELSIF UPDATING THEN
        INSERT INTO audit_log (table_name, action, record_id,
                old_values, new_values)
        VALUES ('CUSTOMERS', 'UPDATE', :OLD.customer_id,
                'first_name=' || :OLD.first_name,
                'first_name=' || :NEW.first_name);
    ELSIF DELETING THEN
        INSERT INTO audit_log (table_name, action, record_id, old_values)
        VALUES ('CUSTOMERS', 'DELETE', :OLD.customer_id,
                'first_name=' || :OLD.first_name || ', email=' || :OLD.email);
    END IF;
END;
/

FAQ

What is the difference between Oracle XE and Enterprise Edition?
XE is free but limited to 12GB user data, 2GB RAM, and 2 CPUs. Enterprise Edition has no limits and includes advanced features like RAC, partitioning, and Data Guard. Use XE for learning and SE2/EE for production.
How do I reset a user password in Oracle?
Login as SYSTEM or a DBA user: ALTER USER username IDENTIFIED BY new_password;. Then the user can connect with the new password.
What is a tablespace in Oracle?
A tablespace is a logical storage unit that groups related data files. Every table belongs to a tablespace. Default ones are SYSTEM, SYSAUX, USERS, and TEMP for temporary data.
Does Oracle support JSON?
Yes, since Oracle 12c. Use JSON data type, JSON_EXISTS, JSON_TABLE, and JSON_VALUE functions. Oracle even has a SODA (Simple Oracle Document Access) API for document-style access.
How do I find slow queries in Oracle?
Query V$SQL for execution statistics, enable AWR (Automatic Workload Repository) reports, or use DBMS_XPLAN.DISPLAY to see execution plans. The V$SESSION_LONGOPS view shows currently running long operations.

Try It Yourself

Create the customers and orders schema above in Oracle XE, then run these queries:

-- Which customers haven't ordered anything?
SELECT c.first_name, c.last_name
FROM customers c
WHERE NOT EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id);

-- Monthly order summary
SELECT
    TO_CHAR(order_date, 'YYYY-MM') AS month,
    COUNT(*) AS orders,
    SUM(total_amount) AS revenue
FROM orders
GROUP BY TO_CHAR(order_date, 'YYYY-MM')
ORDER BY month;

-- Customer ranking by total spend
SELECT
    first_name || ' ' || last_name AS customer,
    NVL(SUM(total_amount), 0) AS total_spent,
    RANK() OVER (ORDER BY NVL(SUM(total_amount), 0) DESC) AS rank
FROM customers c
LEFT JOIN orders o ON c.customer_id = o.customer_id
GROUP BY c.customer_id, first_name, last_name;

These query patterns are used by DodaZIP for cloud file audit trails and by Durga Antivirus Pro for analyzing threat detection patterns across enterprise deployments.

What’s Next

Congratulations on completing this Oracle Database tutorial! Here’s where to go from here:

  • Practice daily — Consistency is more important than long study sessions
  • Build a project — Apply what you learned by building something real
  • Explore related topics — Check out other tutorials in the same category
  • Join the community — Discuss with other learners and share your progress

Remember: every expert was once a beginner. Keep coding!

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro