Skip to main content

What is Data Manipulation Language (DML)?

Data Manipulation Language (DML) is the subset of SQL commands exclusively responsible for managing and modifying the data stored within database tables. DML specifically refers to the “CRUD” operations: Creating (inserting), Reading (querying), Updating, and Deleting data.
The core purpose of DML is to enable applications to interact with and change the state of the data, solving the fundamental problem of persisting and maintaining application data in an organized, efficient, and controlled manner within a relational database.

INSERT Statement

The INSERT statement adds new rows of data to a table. You specify the target table, the columns you’re populating, and the corresponding values.
DECLARE
  v_emp_id employees.employee_id%TYPE := 1000;
BEGIN
  -- Inserting a single row using variables for dynamic values
  INSERT INTO employees (
    employee_id, first_name, last_name, email, hire_date, job_id
  ) VALUES (
    v_emp_id, 'Alice', 'Smith', 'ASMITH', SYSDATE, 'IT_PROG'
  );
  
  DBMS_OUTPUT.PUT_LINE('Employee ' || v_emp_id || ' inserted.');
  
  -- Inserting multiple rows based on a SELECT query
  INSERT INTO archived_employees (emp_id, name)
  SELECT employee_id, first_name || ' ' || last_name
  FROM employees
  WHERE hire_date < DATE '2000-01-01';
  
  DBMS_OUTPUT.PUT_LINE('Archived old employees.');
END;
/

UPDATE Statement

The UPDATE statement modifies existing data in one or more rows of a table. You specify the table to update, the columns to change with their new values using the SET clause, and a WHERE clause to define which rows should be affected.
Omitting the WHERE clause will update every row in the table, which is often dangerous and requires caution.
DECLARE
  v_department_id departments.department_id%TYPE := 60;
  v_salary_increase_percent NUMBER := 0.10; -- 10% increase
BEGIN
  -- Update salaries for a specific department
  UPDATE employees
  SET salary = salary * (1 + v_salary_increase_percent)
  WHERE department_id = v_department_id;
  
  -- Use SQL%ROWCOUNT to get the number of rows affected
  DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' employees received a raise.');
  
  -- A more complex update using a subquery
  UPDATE employees e
  SET salary = (
    SELECT MAX(salary) * 1.05
    FROM employees
    WHERE department_id = e.department_id
  )
  WHERE e.employee_id = 100;
END;
/

DELETE Statement

The DELETE statement removes one or more rows from a table. Similar to UPDATE, you specify the target table and a WHERE clause to identify the rows to be removed.
DECLARE
  v_cutoff_date DATE := ADD_MONTHS(SYSDATE, -60); -- 5 years ago
BEGIN
  -- Delete inactive orders older than 5 years
  DELETE FROM orders
  WHERE status = 'CANCELLED'
  AND order_date < v_cutoff_date;
  
  DBMS_OUTPUT.PUT_LINE(SQL%ROWCOUNT || ' old orders purged.');
  
  -- Conditional delete based on program logic
  IF some_condition THEN
    DELETE FROM temp_logging_table;
    DBMS_OUTPUT.PUT_LINE('Temporary log cleared.');
  END IF;
END;
/

MERGE Statement

The MERGE statement (also known as UPSERT - UPDATE or INSERT) performs a conditional insert or update operation in a single, atomic statement.
MERGE is powerful for synchronizing data between staging and production tables efficiently.
BEGIN
  -- Sync the target 'products' table with updates from 'products_staging'
  MERGE INTO products t
  USING products_staging s
  ON (t.product_id = s.product_id)
  WHEN MATCHED THEN
    UPDATE SET
      t.product_name = s.product_name,
      t.price = s.price,
      t.last_updated = SYSDATE
    WHERE t.price != s.price -- Only update if the price actually changed
  WHEN NOT MATCHED THEN
    INSERT (product_id, product_name, price, created_date)
    VALUES (s.product_id, s.product_name, s.price, SYSDATE);
    
  DBMS_OUTPUT.PUT_LINE('Products table synchronized.');
END;
/

Transaction Control

A transaction is a logical unit of work comprising one or more DML statements. Transaction control ensures ACID properties (Atomicity, Consistency, Isolation, Durability).
Always use explicit transaction control (COMMIT/ROLLBACK) for data integrity.
BEGIN
  -- This is a single transaction
  UPDATE account SET balance = balance - 100 WHERE id = 1; -- Withdraw
  UPDATE account SET balance = balance + 100 WHERE id = 2; -- Deposit
  
  -- If both updates succeed, make the changes permanent.
  COMMIT;
  DBMS_OUTPUT.PUT_LINE('Funds transferred successfully.');
  
EXCEPTION
  -- If ANY error occurs, undo BOTH changes.
  WHEN OTHERS THEN
    ROLLBACK;
    DBMS_OUTPUT.PUT_LINE('Transfer failed. Changes rolled back.');
    RAISE; -- Re-raise the error to the calling environment
END;
/

COMMIT Statement

The COMMIT statement makes all changes performed in the current transaction permanent. Once a COMMIT is issued, the changes become visible to other database sessions.
BEGIN
  INSERT INTO audit_log (user_name, action) VALUES ('USER_A', 'Started process');
  -- ... more DML operations ...
  COMMIT; -- Finalize the entire batch of work
END;
/

ROLLBACK Statement

The ROLLBACK statement undoes all changes made in the current transaction, reverting the database to its state before the transaction began.
BEGIN
  SAVEPOINT before_complex_operation;
  
  -- Complex multi-step process...
  UPDATE table_a ...;
  DELETE FROM table_b ...;
  
  IF some_business_rule_is_violated THEN
    ROLLBACK TO before_complex_operation; -- Or just ROLLBACK;
    DBMS_OUTPUT.PUT_LINE('Operation aborted.');
  ELSE
    COMMIT;
  END IF;
END;
/

SAVEPOINT Statement

The SAVEPOINT statement sets a named point within a transaction to which you can later roll back.
SAVEPOINT allows for partial rollbacks without undoing the entire transaction.
BEGIN
  INSERT INTO main_table (data) VALUES ('Step 1 Data');
  SAVEPOINT after_step_1;
  
  BEGIN
    -- A risky operation that might fail
    UPDATE another_table SET ...;
  EXCEPTION
    WHEN OTHERS THEN
      -- On failure, only undo the risky step, keeping the initial insert.
      ROLLBACK TO after_step_1;
      DBMS_OUTPUT.PUT_LINE('Risky step failed, rolled back to savepoint.');
  END;
  
  -- This insert will happen regardless of the above exception
  INSERT INTO main_table (data) VALUES ('Final Step Data');
  COMMIT;
END;
/

Why is DML Important?

Enables Data Integrity through Atomicity (ACID)

DML operations wrapped in transactions ensure that complex business operations (like a financial transfer) succeed or fail completely, preventing data corruption and maintaining logical consistency.

Promotes Modularity and the DRY Principle

By encapsulating DML logic within well-defined PL/SQL procedures and functions, you avoid scattering raw SQL across an application. This centralizes business rules, making the codebase more maintainable, testable, and secure.

Facilitates Performance and Scalability

Using set-based DML operations (like a single UPDATE affecting thousands of rows) is vastly more efficient than procedural row-by-row processing.

Advanced Nuances

RETURNING INTO Clause

Use RETURNING INTO to avoid extra queries after DML operations.
DECLARE
  v_new_key NUMBER;
BEGIN
  INSERT INTO my_table (id, data)
  VALUES (my_seq.NEXTVAL, 'New Data')
  RETURNING id INTO v_new_key; -- Capture the new sequence value immediately
END;
/

Bulk Operations (FORALL)

For performance-critical applications, use FORALL to send batches of DML statements:
DECLARE
  TYPE IdList IS TABLE OF NUMBER;
  l_ids IdList := IdList(101, 102, 103);
BEGIN
  FORALL i IN l_ids.FIRST .. l_ids.LAST
    UPDATE employees SET salary = salary * 1.1
    WHERE employee_id = l_ids(i);
END;
/

INSTEAD OF Triggers

On complex views involving joins, use INSTEAD OF triggers to enable DML operations.
An INSTEAD OF trigger can be created on a view to intercept DML commands and redirect them to the appropriate base tables with custom logic.

How This Fits the Roadmap

Within the “Advanced SQL Features” section of the PL/SQL Mastery roadmap, DML is the fundamental bedrock.

Prerequisites For:

  • Dynamic SQL - EXECUTE IMMEDIATE with DML
  • Bulk Processing - BULK COLLECT, FORALL
  • Advanced Cursors - Updating rows fetched from a cursor

Unlocks:

  • Robust data processing logic
  • High-performance ETL processes
  • Complex business rules in stored procedures
  • Sophisticated triggers
  • Scalable, reliable database-centric applications

Build docs developers (and LLMs) love