INSERT, UPDATE, DELETE in SQL Server: The Mistake That Wipes Your Table

INSERT, UPDATE, DELETE in SQL Server: The Mistake That Wipes Your Table

DML (Data Manipulation Language) statements change the data inside tables, not their structure. They’re also where the single most expensive beginner mistake in SQL happens — and where a handful of less-obvious patterns (multi-row inserts, UPDATE with a JOIN, the OUTPUT clause) separate someone who can write basic DML from someone who’s actually fluent.

INSERT · UPDATE · DELETE(and the missing WHERE that costs careers)INSERTadds new rowsUPDATEchanges existing rowsDELETEremoves rows, foreversame WHERE clause. wildly different stakes:UPDATE Employee SET salary=salary*1.05WHERE last_name=’Sharma’;exactly one row changesUPDATE Employee SET salary=0;— no WHERE clause at all😱 EVERY row. No undo.TRUNCATE isn’t DELETE:no WHERE, resets IDENTITY,skips triggers entirely.safe habit: SELECT the same WHERE first, then run the UPDATE

INSERT: One Row, Many Rows, or From Another Query

-- Single row
INSERT INTO dbo.Employee (first_name, last_name, hire_date, salary)
VALUES ('Priya', 'Sharma', '2024-03-01', 75000.00);

-- Multiple rows in one statement — one round trip instead of three
INSERT INTO dbo.Employee (first_name, last_name, hire_date, salary)
VALUES
    ('Alex', 'Chen', '2024-04-10', 68000.00),
    ('Jordan', 'Lee', '2024-05-02', 71000.00),
    ('Sam', 'Patel', '2024-05-15', 69500.00);

-- INSERT ... SELECT — copy rows from another table/query, no VALUES needed
INSERT INTO dbo.Employee_Archive (first_name, last_name, hire_date, salary)
SELECT first_name, last_name, hire_date, salary
FROM dbo.Employee
WHERE hire_date < '2020-01-01';

INSERT ... SELECT is one of the most-used patterns in real T-SQL — archiving old rows, seeding a new table from an existing one, or building the exact kind of synthetic test data later chapters use for performance work.

UPDATE and DELETE: The Basics

UPDATE dbo.Employee
SET salary = salary * 1.05
WHERE last_name = 'Sharma';

DELETE FROM dbo.Employee
WHERE employee_id = 2;

TRUNCATE TABLE dbo.Employee; -- wipes ALL rows instantly, resets IDENTITY

UPDATE Driven by Another Table

A pattern beginners often don't discover for a while: updating one table based on values in another, using a JOIN directly inside the UPDATE:

UPDATE e
SET e.salary = e.salary * 1.10
FROM dbo.Employee e
JOIN dbo.Department d ON d.department_id = e.department_id
WHERE d.name = 'Engineering';

This gives every Engineering employee a 10% raise in one statement, without needing to first SELECT the matching IDs into a list. You'll get comfortable with the JOIN syntax itself in Chapter 5 — file this pattern away for later.

DELETE vs TRUNCATE: Not Interchangeable

DELETE TRUNCATE
WHERE clause Supported — delete a subset Not allowed — always removes every row
Logging Logs each row individually Minimally logged — much faster on large tables
IDENTITY counter Unaffected — next insert continues numbering Reset back to the seed value
Triggers Fires any DELETE triggers Does not fire DELETE triggers
Foreign keys Works even if referenced by another table (row by row) Fails if any other table has a foreign key pointing to this one

Rule of thumb: reach for TRUNCATE only when you genuinely mean "empty this entire table and I don't care about triggers or per-row logging" — typically scratch/staging tables. For anything with a WHERE clause, or that has triggers or dependent foreign keys, DELETE is the only option anyway.

The Mistake That Costs Careers

UPDATE Employee SET salary = 0 WHERE employee_id = 2; ✅ Updates exactly one row UPDATE Employee SET salary = 0; ❌ Zeroes out EVERY row in the table — no confirmation, no undo

Without a WHERE clause, UPDATE and DELETE apply to every row in the table. Always verify your WHERE clause as a SELECT first:

-- Step 1: verify what you're about to change
SELECT * FROM dbo.Employee WHERE last_name = 'Sharma';

-- Step 2: only then run the UPDATE with the identical WHERE clause
UPDATE dbo.Employee SET salary = salary * 1.05 WHERE last_name = 'Sharma';

A Safer Habit: OUTPUT and Transactions

Two techniques that make destructive DML meaningfully safer in practice. First, OUTPUT shows you exactly what changed, immediately:

UPDATE dbo.Employee
SET salary = salary * 1.05
OUTPUT deleted.employee_id, deleted.salary AS old_salary, inserted.salary AS new_salary
WHERE last_name = 'Sharma';

Second, wrap risky DML in an explicit transaction so a mistake is one ROLLBACK away instead of permanent:

BEGIN TRAN;
UPDATE dbo.Employee SET salary = 0; -- oops, forgot the WHERE clause
SELECT * FROM dbo.Employee; -- immediately obvious something's wrong
ROLLBACK; -- undone, no harm done
Practice tip: For any UPDATE/DELETE you're not fully confident in outside of a script you've tested, run it inside BEGIN TRAN ... ROLLBACK first as a dry run. Only re-run with COMMIT once the row count and OUTPUT look exactly right.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it's published, and share it with a developer who'd find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server Fundamentals, coming soon on this site.