Data Manipulation

INSERT, UPDATE, DELETE operations

Modifying Data in Databases

So far we've only read data with SELECT. Now we'll learn how to create, modify, and delete data. These operations, INSERT, UPDATE, and DELETE, are collectively known as DML (Data Manipulation Language). They're how you actually change what's stored in your database. Be careful: unlike SELECT, these operations permanently modify your data.

Starting Table: employees

We'll modify this table throughout the lesson:

┌────┬────────────┬───────────┬─────────────┬────────┐
│ id │ first_name │ last_name │ department  │ salary │
├────┼────────────┼───────────┼─────────────┼────────┤
│ 1  │ Alice      │ Johnson   │ Engineering │ 95000  │
│ 2  │ Bob        │ Smith     │ Marketing   │ 65000  │
│ 3  │ Charlie    │ Brown     │ Engineering │ 105000 │
└────┴────────────┴───────────┴─────────────┴────────┘

INSERT: Adding New Data

INSERT adds new rows to a table. You specify which columns to fill and what values to use.

Insert One Row

Add a single employee with all required fields.

INSERT INTO employees (id, first_name, last_name, department, salary)
VALUES (4, 'Diana', 'Martinez', 'Sales', 72000);

Result: 1 row inserted

Table now contains:
┌────┬────────────┬───────────┬─────────────┬────────┐
│ id │ first_name │ last_name │ department  │ salary │
├────┼────────────┼───────────┼─────────────┼────────┤
│ 1  │ Alice      │ Johnson   │ Engineering │ 95000  │
│ 2  │ Bob        │ Smith     │ Marketing   │ 65000  │
│ 3  │ Charlie    │ Brown     │ Engineering │ 105000 │
│ 4  │ Diana      │ Martinez  │ Sales       │ 72000  │ ← NEW
└────┴────────────┴───────────┴─────────────┴────────┘

Insert Partial Data

You don't need to specify every column, omitted columns get NULL or their default values.

INSERT INTO employees (id, first_name, last_name)
VALUES (5, 'Eve', 'Davis');

Result: department and salary will be NULL

┌────┬────────────┬───────────┬────────────┬────────┐
│ id │ first_name │ last_name │ department │ salary │
├────┼────────────┼───────────┼────────────┼────────┤
│ 5  │ Eve        │ Davis     │ NULL       │ NULL   │
└────┴────────────┴───────────┴────────────┴────────┘

Insert Multiple Rows

Insert several rows in a single statement (more efficient).

INSERT INTO employees (id, first_name, last_name, department, salary)
VALUES 
    (6, 'Frank', 'Wilson', 'Marketing', 70000),
    (7, 'Grace', 'Lee', 'Sales', 78000),
    (8, 'Henry', 'Taylor', 'Engineering', 92000);

Result: 3 rows inserted at once

Added to table:
│ 6  │ Frank      │ Wilson    │ Marketing   │ 70000  │
│ 7  │ Grace      │ Lee       │ Sales       │ 78000  │
│ 8  │ Henry      │ Taylor    │ Engineering │ 92000  │

Insert from Another Table

Copy data from one table to another using SELECT.

INSERT INTO employees_archive (id, first_name, last_name)
SELECT id, first_name, last_name
FROM employees
WHERE department = 'Sales';

Copies all Sales employees to the archive table

Column Order Matters: The VALUES must match the column order you specified. If you list columns as (name, salary), VALUES must be ('Alice', 95000), not (95000, 'Alice').

UPDATE: Modifying Existing Data

UPDATE changes values in existing rows. Always use a WHERE clause unless you want to update every row.

Update One Row

Give Alice a raise.

UPDATE employees
SET salary = 100000
WHERE id = 1;

Before:

│ 1  │ Alice      │ Johnson   │ Engineering │ 95000  │

After:

│ 1  │ Alice      │ Johnson   │ Engineering │ 100000 │ ← Updated

Update Multiple Columns

Bob gets promoted and a raise.

UPDATE employees
SET 
    department = 'Engineering',
    salary = 85000
WHERE id = 2;

Before:

│ 2  │ Bob        │ Smith     │ Marketing   │ 65000  │

After:

│ 2  │ Bob        │ Smith     │ Engineering │ 85000  │ ← Both changed

Update Multiple Rows

Give all Marketing employees a 10% raise.

UPDATE employees
SET salary = salary * 1.10
WHERE department = 'Marketing';

Result: All Marketing employees get 10% increase

Before:  Frank: $70,000
After:   Frank: $77,000 (70000 * 1.10)

Conditional Update

Update only if certain conditions are met.

UPDATE employees
SET salary = salary + 5000
WHERE department = 'Engineering' AND salary < 90000;

Only Engineering employees earning less than $90k get the bonus

⚠️ Critical Warning: Forgetting WHERE updates EVERY row!
-- DISASTER: Sets everyone's salary to 50000
UPDATE employees SET salary = 50000;

-- SAFE: Only updates specific employee
UPDATE employees SET salary = 50000 WHERE id = 2;

DELETE: Removing Data

DELETE removes rows from a table permanently. There's no undo button.

Delete One Row

Remove a specific employee by ID.

DELETE FROM employees
WHERE id = 5;

Before: 8 employees

│ 5  │ Eve        │ Davis     │ NULL        │ NULL   │ ← Will be deleted

After: 7 employees (Eve is gone)

Delete Multiple Rows

Remove all employees from a specific department.

DELETE FROM employees
WHERE department = 'Sales';

Result: Removes Diana and Grace (both in Sales)

Deleted:
│ 4  │ Diana      │ Martinez  │ Sales       │ 72000  │ ✗
│ 7  │ Grace      │ Lee       │ Sales       │ 78000  │ ✗

Delete with Complex Condition

Remove employees meeting multiple criteria.

DELETE FROM employees
WHERE salary < 70000 AND department = 'Marketing';

Only removes Marketing employees earning less than $70k

Delete All Rows (Dangerous!)

Remove everything from the table (structure remains).

DELETE FROM employees;

Warning: Deletes all rows! Table is now empty.

Before: 8 rows
After:  0 rows (but table structure still exists)
🚨 Extreme Danger: DELETE without WHERE removes ALL rows!
Always test with SELECT first:
-- Step 1: TEST with SELECT
SELECT * FROM employees WHERE id = 5;

-- Step 2: Verify it returns what you expect

-- Step 3: THEN delete
DELETE FROM employees WHERE id = 5;

TRUNCATE: Fast Delete All

TRUNCATE removes all rows instantly, faster than DELETE. Cannot be undone and has no WHERE clause.

TRUNCATE TABLE employees;

Immediately removes all rows, resets auto-increment counters

TRUNCATE vs DELETE
  • TRUNCATE: Faster, removes all rows, resets counters, can't have WHERE
  • DELETE: Slower, can use WHERE, can be rolled back in transactions

RETURNING: Get Data Back

Some databases (PostgreSQL) let you see what was inserted, updated, or deleted.

INSERT with RETURNING

INSERT INTO employees (first_name, last_name, salary)
VALUES ('John', 'Doe', 80000)
RETURNING id, first_name, salary;
Returns:
┌────┬────────────┬────────┐
│ id │ first_name │ salary │
├────┼────────────┼────────┤
│ 9  │ John       │ 80000  │ ← Shows newly created row
└────┴────────────┴────────┘

UPDATE with RETURNING

UPDATE employees
SET salary = salary * 1.10
WHERE department = 'Engineering'
RETURNING first_name, salary;
Shows all updated rows with new salaries:
┌────────────┬────────┐
│ first_name │ salary │
├────────────┼────────┤
│ Alice      │ 110000 │
│ Charlie    │ 115500 │
│ Henry      │ 101200 │
└────────────┴────────┘

Best Practices & Safety

✅ Always Use WHERE

Unless you genuinely want to affect every row, always include a WHERE clause in UPDATE and DELETE statements.

✅ Test with SELECT First

Before UPDATE or DELETE, run a SELECT with the same WHERE clause to see what will be affected.

✅ Use Transactions

Wrap dangerous operations in BEGIN/COMMIT so you can ROLLBACK if something goes wrong.

✅ Backup Before Bulk Changes

Before running large UPDATEs or DELETEs on production, always have a recent backup.

❌ Never Run in Production Without Testing

Test all data manipulation queries on development or staging databases first.

Using Transactions for Safety

Transactions let you test changes before making them permanent.

-- Start transaction
BEGIN;

-- Make changes
UPDATE employees SET salary = salary * 1.20 WHERE department = 'Engineering';

-- Check if it looks correct
SELECT * FROM employees WHERE department = 'Engineering';

-- If good: make it permanent
COMMIT;

-- If bad: undo everything
ROLLBACK;

Changes aren't permanent until COMMIT. Use ROLLBACK to undo.

Key Takeaways

  • INSERT adds new rows to a table
  • UPDATE modifies existing rows - always use WHERE
  • DELETE removes rows - always use WHERE
  • TRUNCATE removes all rows quickly
  • Test with SELECT first before UPDATE or DELETE
  • Use transactions to safely test changes
  • RETURNING shows affected rows (PostgreSQL)
  • Data manipulation is permanent, there's no undo button, so always be cautious and test thoroughly