DBMSCSL303 / MAL505
Module 4: Programming, Security & Transactions

Lecture 10: DML, Triggers & Python DB-API

Modifying Data Safely (INSERT, UPDATE, DELETE, UPSERT), Triggers, Python sqlite3, and Preventing SQL Injection

Lecture Source Slide Deck

Original Slides: Lecture 10 (53 slides) · Amit Kumar Dhar (IIT Bhilai)
Download lecture10.pdf

1. Full Data Manipulation Language (DML)

1. INSERT Varieties

-- Single row insert with explicit columns
INSERT INTO student (id, name, dept_name, tot_cred)
VALUES ('98988', 'Tanaka', 'Biology', 0);

-- Multi-row insert
INSERT INTO department (dept_name, building, budget) VALUES
    ('Data Science', 'Alan Turing', 900000),
    ('Robotics', 'Grace Hopper', 750000);

-- Bulk insert from a query
INSERT INTO faculty_archive
SELECT * FROM instructor WHERE salary < 40000;

2. UPDATE

-- Increase salaries of Comp. Sci. instructors by 5%
UPDATE instructor
SET salary = salary * 1.05
WHERE dept_name = 'Comp. Sci.';

The Forgotten WHERE Clause

Executing UPDATE instructor SET salary = 100000; without a WHERE clause will overwrite every single row in the table! Always write the WHERE clause first.

3. DELETE vs. TRUNCATE vs. DROP

  • DELETE FROM t WHERE condition: Removes matching rows, fires row-level triggers, logs each row removal.
  • TRUNCATE TABLE t: Deallocates data pages instantly, resets auto-increment sequences, bypasses row triggers, retains table schema.
  • DROP TABLE t: Completely removes the table definition, constraints, and data from the catalog.

4. UPSERT (ON CONFLICT)

Modern databases (PostgreSQL, SQLite 3.24+) allow insert-or-update behavior atomically:

INSERT INTO course_views (course_id, view_count)
VALUES ('CS-101', 1)
ON CONFLICT (course_id) DO UPDATE SET
    view_count = course_views.view_count + 1;

2. Database Triggers

A Trigger is a procedural block of code stored in the database that is automatically executed ("fired") by the database engine whenever a specified event (INSERT, UPDATE, DELETE) occurs on a table.

Trigger Event: [ INSERT / UPDATE / DELETE ]
Timing:        [ BEFORE | AFTER | INSTEAD OF ]
Granularity:   [ FOR EACH ROW | FOR EACH STATEMENT ]

Trigger Pseudorecords

  • OLD: Holds attribute values of the row before the modification (UPDATE, DELETE).
  • NEW: Holds the prospective attribute values being inserted or updated (INSERT, UPDATE).
-- Example: Audit salary modifications into an audit log
CREATE TRIGGER audit_instructor_salary
AFTER UPDATE OF salary ON instructor
FOR EACH ROW
WHEN (OLD.salary <> NEW.salary)
BEGIN
    INSERT INTO salary_log (instructor_id, old_sal, new_sal, changed_at)
    VALUES (OLD.id, OLD.salary, NEW.salary, DATETIME('now'));
END;

3. Python Database Programming (PEP 249 DB-API)

Applications communicate with relational databases via client drivers adhering to the Python DB-API standard:

import sqlite3
import sys

# 1. Establish connection
conn = sqlite3.connect("university.db")

# 2. Access columns by name like dictionary keys
conn.row_factory = sqlite3.Row
cur = conn.cursor()

# 3. Always enable foreign keys in SQLite
cur.execute("PRAGMA foreign_keys = ON;")

dept = sys.argv[1] if len(sys.argv) > 1 else "Comp. Sci."

# 4. Safe parameterized query (NEVER use f-strings or string concatenation!)
cur.execute("SELECT name, salary FROM instructor WHERE dept_name = ?", (dept,))

for row in cur.fetchall():
    print(f"{row['name']}: ${row['salary']:,.2f}")

# 5. Commit mutations and close
conn.commit()
conn.close()

4. SQL Injection Vulnerabilities & Prevention

The Catastrophic Flaw: String Interpolation

# VULNERABLE CODE: NEVER DO THIS!
user_input = "Comp. Sci.' OR '1'='1"
query = f"SELECT * FROM instructor WHERE dept_name = '{user_input}';"
cur.execute(query)

The resulting executed query becomes:

SELECT * FROM instructor WHERE dept_name = 'Comp. Sci.' OR '1'='1';

This bypasses authentication or leaks the entire table! If an attacker enters '; DROP TABLE student; --, entire databases can be erased.

The Solution: Parameterized Placeholders

With parameterized queries (? in SQLite, %s in Postgres), user input is sent as raw literal data in a separate protocol phase; the SQL compiler treats it strictly as a value, never executable code.


5. Topic Practice Questions

On this page