Tag: DDL & DML

  • 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.

  • CREATE, ALTER, DROP: SQL Server DDL Explained With Examples

    CREATE, ALTER, DROP: SQL Server DDL Explained With Examples

    DDL (Data Definition Language) statements define the structure of your database โ€” tables, columns, and their types. Every DDL statement in SQL Server takes effect immediately and, unusually among major databases, is fully transactional โ€” you can wrap DDL in BEGIN TRAN/ROLLBACK and undo it, which most other RDBMSes don’t allow.

    Build, Change, Destroy(and how to undo any of it)wrap ANY of these in BEGIN TRAN … ROLLBACK to undoCREATEbuild something newALTERcan fail if data doesn’t fitDROPgone. no undo. ever.risk increases โ†’CREATE TABLE IF NOT EXISTSis NOT valid T-SQL! Use:IF OBJECT_ID(…) IS NULLBEGIN … END instead.

    CREATE: Build a New Table

    CREATE TABLE dbo.Employee (
        employee_id   INT IDENTITY(1,1) PRIMARY KEY,
        first_name    NVARCHAR(50)  NOT NULL,
        last_name     NVARCHAR(50)  NOT NULL,
        hire_date     DATE          NOT NULL DEFAULT GETDATE(),
        salary        DECIMAL(10,2) NOT NULL
    );

    Notice the dbo. prefix โ€” that’s the schema name. dbo (database owner) is the default schema every database starts with; schemas are namespaces that let you group related tables (e.g. sales.Order vs hr.Employee) and manage permissions per group. Always schema-qualify your table names in real code โ€” unqualified names resolve against whatever the current user’s default schema happens to be, which is a subtle source of “works on my machine” bugs.

    Guarding CREATE Against Re-Running a Script

    CREATE TABLE IF NOT EXISTS dbo.Scratch_Test (id INT); -- NOT valid T-SQL!
    
    -- The actual SQL Server idiom:
    IF OBJECT_ID('dbo.Scratch_Test', 'U') IS NULL
    BEGIN
        CREATE TABLE dbo.Scratch_Test (id INT);
    END
    Common mistake: Copying CREATE TABLE IF NOT EXISTS syntax from MySQL/PostgreSQL tutorials โ€” it’s a syntax error in T-SQL. The OBJECT_ID(...) IS NULL check above is the standard SQL Server equivalent, and you’ll see it constantly in real migration scripts.

    ALTER: Change an Existing Table

    ALTER TABLE dbo.Employee ADD email NVARCHAR(100) NULL;
    ALTER TABLE dbo.Employee ALTER COLUMN salary DECIMAL(12,2) NOT NULL;
    ALTER TABLE dbo.Employee DROP COLUMN email;

    Two things about ALTER COLUMN that surprise beginners: first, widening a type (DECIMAL(10,2) โ†’ DECIMAL(12,2), or VARCHAR(50) โ†’ VARCHAR(100)) is safe and fast. Narrowing one โ€” or changing NULL to NOT NULL on a column that already has NULL values โ€” fails outright if existing data can’t fit the new definition. SQL Server checks every existing row before allowing the change.

    -- This fails if any existing row has a NULL email:
    ALTER TABLE dbo.Employee ALTER COLUMN email NVARCHAR(100) NOT NULL;
    -- Msg 515: Cannot insert the value NULL into column 'email' ...
    
    -- The real-world fix: clean the data first, then tighten the constraint
    UPDATE dbo.Employee SET email = 'unknown@example.com' WHERE email IS NULL;
    ALTER TABLE dbo.Employee ALTER COLUMN email NVARCHAR(100) NOT NULL;

    Renaming Things (It’s Not ALTER)

    Unlike some databases, T-SQL doesn’t rename objects through ALTER โ€” it uses a dedicated system procedure:

    EXEC sp_rename 'dbo.Employee.email', 'contact_email', 'COLUMN';
    EXEC sp_rename 'dbo.Employee', 'Staff';
    Caution: sp_rename does not update any views, stored procedures, or application code referencing the old name โ€” it only changes the object’s internal metadata name. Renaming a production table is a bigger operation than it looks.

    DROP: Permanently Remove an Object

    DROP TABLE IF EXISTS dbo.Scratch_Test;

    Unlike CREATE TABLE IF NOT EXISTS, DROP TABLE IF EXISTS genuinely is valid modern T-SQL (SQL Server 2016+) โ€” the asymmetry is just a quirk of which syntax Microsoft added and when.

    The Danger Zone, Visualized

    CREATE / ALTER Safe, reversible-ish DROP TABLE Data + structure, gone. No undo.

    DROP TABLE deletes the table and every row in it, permanently, with no confirmation prompt. Always double-check you’re connected to the right database (SELECT DB_NAME();) before running DROP anywhere near a real environment.

    DDL Is Transactional โ€” Use It

    Because DDL participates in transactions in SQL Server, you can test a risky structural change safely:

    BEGIN TRAN;
    
    ALTER TABLE dbo.Employee DROP COLUMN salary;
    SELECT * FROM dbo.Employee; -- confirm it looks right
    
    ROLLBACK; -- changed your mind โ€” salary column is back, nothing happened
    -- or: COMMIT; -- to make it permanent
    Practice tip: Get in the habit of wrapping any ALTER/DROP you’re not 100% sure about in BEGIN TRAN, checking the result, then COMMIT or ROLLBACK. This one habit prevents most “oops, wrong table” DDL incidents.

    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.